The prototype
Let’s start with a picture.
First, let’s look at the Person constructor. It’s just a normal function:
function Person () {}
Copy the code
Then, with the new operator, we can generate an instance:
var person = new Person()
Copy the code
When we define the Person constructor, we actually generate an object, which is the prototype object. Person.prototype. It’s just a normal object. If we print on the console it looks like this:
{constructor: ƒ Person() __proto__: Object}Copy the code
It has a constructor that executes its constructor. The constructor can access the prototype through the Prototype property.
When we create an instance of person using the new operator, we also associate the instance with its constructor’s prototype via __proto__.
This is the relationship between the constructor, the prototype, and the instance. That’s the idea of a prototype.
Prototype chain
From the above we have a general idea of the prototype. So what is a prototype chain?
Let’s look at Person.prototype. As we mentioned above, a prototype object is just a normal object that has a constructor property pointing to its constructor. It also has an attribute __proto__ that refers to the object’s prototype.
We know that objects can be generated using the Object constructor. As with Personnew an instance of Person that has an attribute __proto__ pointing to Person.prototype.
Prototype objects are also generated through constructors. The Object. So it also has a __proto__ attribute pointing to the prototype of its constructor, object.prototype.
Object. Prototype is also a normal Object, except that it is more similar to Person.prototype. It also has some other properties, let’s print them out:
__defineGetter__: ƒ __defineGetter__() __defineSetter__: ƒ __defineSetter__() hasOwnProperty: ƒ hasOwnProperty() __lookupGetter__: ƒ __lookupGetter__() __lookupSetter__: ƒ __lookupSetter__() isPrototypeOf: ƒ isPrototypeOf() propertyIsEnumerable: ƒ propertyIsEnumerable() toString: ƒ toString() valueOf: ƒ valueOf() toLocaleString: ƒ toLocaleString()set__proto__ : ƒ __proto__ ()}Copy the code
We can see that it defines the getter/setter for the __proto__ property here.
So what is object.prototype. __proto__? From the console we can see that null is returned.
At this point, we can actually see that the Person instance Object we construct from Person is actually associated with Object through the __proto__ property.
And such a chain is called a prototype chain. That’s the blue line in the picture.
So what does the prototype chain do?
Let’s use the person example above. If we try Person.toString () on the console. We will find that [object object] is returned. Leaving aside the reason for returning this, we didn’t actually define the toString method, so why can we call it?
This is the mechanism of using the prototype chain. When js executes this code, it tries to see if there is a toString method on Person, and if it doesn’t find one, it looks at Person.prototype. If you still don’t find it, you’ll go to Object.prototype, which we printed out as well, and which has the toString method. So person.tostring () executes successfully, rather than reporting an error indicating that there is no toString method.
Through the prototype chain we can implement the concept of inheritance from other object-oriented languages.
What is the prototype of Function?
From the console, we can see:
function anonymous() {}
arguments: (...)
caller: (...). length: 0 name:""ƒ ()bind: ƒ bindƒ : ƒ () Symbol(symbol.hasinstance): ƒ [symbol.hasinstance]() get arguments: ƒ ()setGet the arguments: ƒ ()caller: ƒ ()
set callerƒ () __proto__: Object [[FunctionLocation]]: <unknown> [[Scopes]]: Scopes[0]Copy the code
It’s actually an anonymous function. It’s not just an ordinary object. But it also has a __proto__ attribute that points to its prototype, object.prototype.
All constructors (except those returned by bind,call, and arrow functions) have a __proto__ attribute pointing to function. prototype.
Person.__proto === function. prototype Object. __proto = = = Function. The prototype;
Include other built-in constructors, such as Number, String, and so on.
Function.__proto__ === Function. Prototype is true. That’s the case. I understand that these are actually prototype objects built into THE JS language. Same as Object.prototype. The first is the Function prototype. Then, in order for the Function constructor to have direct access to the methods on the prototype, its __proto__ attribute points to the Function’s prototype.
If you do console.log(number.prototype), console.log(date.prototype). You’ll notice that there are some differences. The Number prototype has some specific functions implemented, as does Date.
These are the basic prototype objects that are implemented internally in JS.