This post is synchronously distributed on my Github
This article will not cover the basics, but rather focus on the various difficulties of prototyping.
Take a closer look at this figure and let’s get to the point
prototype
Let’s start with the Prototype property. This is an explicit stereotype property that only functions have. Almost all functions have this property, with one exception
let fun = Function.prototype.bind()
Copy the code
If you create a function this way, you will notice that the function does not have the prototype attribute.
How did Prototype come into being
This property is created automatically when we declare a function.
function Foo() {}
Copy the code
And the value of this property is an object (that is, a stereotype) with only one property constructor
Constructor corresponds to the constructor, which is Foo.
constructor
Constructor is a public and non-enumerable property. Once we have changed the function’s prototype, the new object does not have this property (which can of course be retrieved from constructor via the prototype chain).
So you must have a question, what is the use of this property? In fact, this attribute can be said to be a legacy of history and is useless in most cases. In my understanding, I think it has two functions:
- Let the instance object know what function constructed it
- If you want to add custom methods to the constructors in some libraries, you can do so
xx.constructor.method
To extend the
_proto_
This is an implicit stereotype property for every object, pointing to the stereotype of the constructor that created the object. [[prototype]] is an internal attribute that we can’t access, so use _proto_.
Because there is no concept of class in JS, in order to achieve similar inheritance, through _proto_ object and prototype linked to form prototype chain, so that the object can access the attributes that do not belong to their own.
Instance object_proto_
How it came about
As you can see from the figure above, when we use the new operator, the generated instance object has the _proto_ attribute.
function Foo() {}
// This Function is an instance of Function
// function is a syntactic sugar
// Call new Function internally (...)
Copy the code
So it can be said that during the new process, the new object is appended with _proto_ and linked to the prototype of the constructor.
The process of new
- The freshman became an object
- Link to the prototype
- Binding this
- Return a new object
All four of these things happen during a call to new, and we can try to implement a new ourselves
function create() {
// Create an empty object
let obj = new Object(a)// Get the constructor
let Con = [].shift.call(arguments)
// Link to the prototype
obj.__proto__ = Con.prototype
// Bind this to the constructor
let result = Con.apply(obj, arguments)
// Make sure new comes out as an object
return typeof result === 'object' ? result : obj
}
Copy the code
For instance objects, both are generated by new, whether function Foo() or let a = {b: 1}.
For creating an object, it is more recommended to create objects in a literal manner. Because you use new Object() to create objects you need to find them layer by layer through the scope chain, but you don’t have this problem with literals.
function Foo() {}
// function is a syntax candy
// Internal equivalent of new Function()
let a = { b: 1 }
// This literal also uses new Object() inside
Copy the code
Function.proto === Function.prototype
__proto__ === Function. Prototype === Function. Prototype === Function.
The answer is definitely no. To illustrate this problem, let’s start with Object.
Object. Prototype is also an Object, but this Object is not created by Object. Instead, the engine creates object.Prototype itself. So it can be said that all instances are objects, but objects are not necessarily instances.
Function.prototype is a special object that, if you print it out in your browser, is actually a Function.
New Function(); Function. Prototype (); new Function(); The answer is no, this function is also created by the engine itself. Prototype is first created by the engine and then function. prototype is created and the two are connected by __proto__. Let fun = function.prototype.bind () has no prototype property. Because function. prototype is an object created by the engine, the engine doesn’t think it needs to add a Prototype attribute to this object.
So again, we can conclude that not all functions arenew Function()
.
Function(); Function(); Function();
Function.__proto__ === function. prototype [prototype] Function() [prototype] Function() [prototype] Function() Function.__proto__ = Function. Prototype All other constructors can be found in the prototype chain, and Function Function() is essentially a Function. Function. Prototype = function. Prototype = function. Prototype = function. Prototype = function.
conclusion
Object
Is the father of all objects. All objects can pass__proto__
To find itFunction
Is the father of all functions, all functions can pass__proto__
To find itFunction.prototype
和Object.prototype
Are two special objects that are created by the engine- Except for the above two special objects, all objects are through the constructor
new
Out of the - Function of the
prototype
It’s an object, which is a prototype - The object’s
__proto__
Pointing to the prototype,__proto__
The prototype chain is formed by connecting objects and stereotypes