I can’t say enough about the importance of stereotypes and prototype chains as a core aspect of JavaScript. However, I have noticed that there are many documents, tutorials or books that describe the prototype and the prototype chain but are not very clear, which is not easy to sort out and understand.

This article mainly describes the basic content of prototype and prototype chain clearly by means of diagrams. OK, let’s start next

The prototype

In general, we write a constructor like this:

function Person () {
    / /...
}
Copy the code

We’re not writing any code in this constructor, but when we print out the constructor from console.dir on the browser console, we see that it has a property called Prototype added.

The constructorPersonthroughprototypeProperty to access its prototype object,Person.prototypeThat’s the prototype object

When we need to create an instance through the Person constructor, we usually write:

function Person () {
    / /...
}
const person = new Person() // Create an instance with the new operator
console.log(person instanceof Person) // true
Copy the code

So can a Person instance access the prototype object of the Person constructor? Apparently it can.

Instances created by new have a __proto__ attribute (note that ⚠ is preceded by two underscores) that gives direct access to the prototype object Person.prototype. In general, we refer to __proto__ attributes as implicit stereotype attributes.

As shown in the figure below

Properties and methods defined on stereotypes can be inherited on instances.

function Person () {
    / /...
}
Person.prototype.sayHi = 'Hi'
const person = new Person() // Create an instance with the new operator
console.log(person.sayHi)   // Hi
console.log(person.__proto__ === Person.prototype) // true
Copy the code

In addition, if the prototype object Person.prototype needs access to its original constructor it can do so through the constructor property, as shown in the following figure

function Person () {
    / /...
}
Person.prototype.sayHi = 'Hi'
const person = new Person() // Create an instance with the new operator
console.log(person.sayHi)   // Hi
console.log(person.__proto__ === Person.prototype)   // true
console.log(Person.prototype.constructor === Person) // true
Copy the code

Prototype chain

When we need to read a property on an instance, JS will first look for the property on the current instance. If not, JS will look for the property by accessing the prototype via __proto__. If so, it can be used directly.

Person.prototype can be thought of as an instance of Object, in which case __proto__ accesses the Object’s prototype Object. Object. Prototype also has a __proto__ attribute, except this time it points to null.

To summarize: When we access properties or methods of an instance (such as Person), we do so in the presentThe instanceIf not found, will beThe prototypeIf you can’t find the prototype, go toPrototype of prototypeSearch, if still can not find to point tonull.

As shown below:

The Person. Prototype mentioned above can be considered an instance of Object.

In fact, we create objects in JS are Object instances, they will inherit the Object prototype Object properties and methods, and create the Object. __proto__ === object.prototype

const obj = {}
console.log(obj.__proto__ === Object.prototype) // true
console.log(obj.toString)  Ζ’ toString() {[native code]

const obj2 = new Object(a)console.log(obj2.__proto__ === Object.prototype) // true
console.log(obj2.toString) Ζ’ toString() {[native code]}
Copy the code

Since Person.prototype can be considered an instance of Object. You can then draw an arrow at Object pointing to Person.prototype to create an instance Object through new.

Finally, adjust the nodes and wires again, resulting in the image shown below

Let’s take a look at some code to further understand the figure above

// Parent class: equivalent to the Person constructor shown above
function Father() {
    this.property = true
}
Father.prototype.getFatherValue = function () {
    return this.property
}
// Subclass: equivalent to the extension in the figure above...
function Son() {
    this.sonProperty = false
}
/ / Father inheritance
Son.prototype = new Father()  
Son.prototype.getSonVaule = function () {
    return this.sonProperty
}

var instance = new Son()
console.log(instance.getFatherValue()) // true inherits methods from Father
console.log(instance.toString) Ζ’ toString() {[native code]
Copy the code

The corresponding figure is as follows:

Understand and memorize this diagram and believe that 80% of the prototype and prototype chain problems will not be difficult to you πŸ˜ƒ

Finally, this article only explains the basic but core knowledge of prototype and prototype chain, and does not explain too much knowledge about inheritance, because it is planned to be put separately in the next article.

If the article if incorrect place, welcome to point out, discuss together πŸ˜‡

reference

Diagram prototypes and prototype chains

Previous JS good article

Full understanding of JavaScript scope and scope chain πŸ”— thoroughly understand scope, execution context, lexical environment πŸ”Ž select 30+ cases and 10 questions to take you through thisπŸ‘Š article summary Promise/async/awaitβœ¨γ€ select output questions and handwritten questions 】 three pieces of code can understand the closure, Why is it so complicated?