All students who engage in front-end development or play JavaScript know that prototype object and prototype chain is one of the most important knowledge points in JavaScript, but also front-end interview questions, so it is imperative to master the prototype and prototype chain. Therefore, I will devote two articles (or more) to prototype objects and prototype chains respectively.

In the previous article, we introduced the constructor execution process and return value in detail, if you did not read, please click the link to JS advanced (1) : everyone can understand the constructor, because it is the basic knowledge of this article.

Without further ado, let’s get to the point.

Why use prototype objects

From the introduction of the last article, we know that:

function Person(name, age) {
    this.name = name;
    this.age = age;
}

var p1 = new Person('Tom', 18);
var p2 = new Person('Jack', 34);
console.log(p1.name, p1.age);   // 'Tom', 18
console.log(p2.name, p2.age);   // 'Jack'And 34Copy the code

However, there may be methods as well as attributes in an object:

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function() {
        console.log('Hello');
    };
}

var p1 = new Person('Tom', 18);
p1.say();  // 'Hello'
var p2 = new Person('Jack', 34);
p2.say();  // 'Hello'
Copy the code

We see that instance P1 and p2 call the same method and both print the result of Hello. But are their memory addresses the same? Let’s print it out:

console.log(p1.say == p2.say); // false
Copy the code

The result is of course false. As we said in the previous article, each call through the constructor opens up a new memory space, so instances P1 and P2 point to different memory addresses. If there are 60 students in the class, we need to call the same method 60 times, but we need to create 60 different memory Spaces, which will cause unnecessary waste. At this point, the prototype object can help us solve this problem.

How to use prototype objects

When a function (note: not just a constructor) is created, it has a prototype property whose value is an object we call a prototype object. Also, as long as you add properties and methods to the prototype object, these properties and methods can be accessed by instances of the function.

Since instances of functions can access properties and methods on prototype objects, we might as well change the above code.

function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.say = function() {
    console.log('Hello');
};

var p1 = new Person('Tom', 18);
var p2 = new Person('Jack', 34);

console.log(p1.say === p2.say); // true
Copy the code

At this point, we see that the say of instance P1 and instance P2 refer to the same memory space. What is the reason for this? Let’s take a look at the console print.

From the screenshot above we can see that Person.prototype seems to be the same as p1.__proto__ and p2.__proto__. To test our guess, we tried printing:

Person.prototype === p1.__proto__;   // true
Person.prototype === p2.__proto__;   // true
p1.__proto__ === p2.__proto___;      // true
Copy the code

We find that all the results are true. This explains why p1.say === p2.say is true.

Draw the constructor — prototype object — instance diagram

Now you have a general understanding of prototype objects and the benefits of using them. Now let’s take a look at the above process by drawing a graph.

Take the following code as an example:

function Person(name) {
    this.name = name;
}

Person.prototype.say = function() {
    console.log('I am saying');
}

var p1 = new Person('Tom');
Copy the code

1. After the Person function is created, a block of memory is created, and there is oneprototypeattribute

2. prototypeThe value of the property is an object, which we call a stereotype object

3. Properties and methods in the prototype object

Referring to the screenshot of the console above, we can see:

(1) On the prototype object, there is a constructor property pointing to Person; (2) On the prototype object, there is a say method, which opens up a new memory space; (3) The prototype object has a __proto__ attribute, which we’ll explain in the next article.

According to our analysis above, continue to draw:

4. Properties and methods in the instance

When p1 instance is created, a new memory space is created. At this point, referring to the screenshot of the console above, we can know:

(1) P1 instance has a name attribute; (2) P1 has a __proto__ attribute that points to the prototype object of the constructor Person.

Based on the above analysis, we continue to draw:

Four,

This should give you an idea of what a prototype object is and why you should use it. Finally, let’s summarize the core knowledge points of this article.

  1. When a function is created, it has a Prototype property whose value is an object. We call the memory space that the prototype property points to the function’s prototype object.

  2. A function’s prototype object has a constructor property that points to the function itself.

function Person() {/ /... } console.log(Person.prototype.constructor === Person); //true
Copy the code
  1. When a function is called as a constructor, an instance of the constructor is generated. This instance will have one__proto__Property that points to the prototype object of the instance’s constructor (also known as the prototype object of the instance).
function Person() {/ /... } var p1 = new Person(); console.log(p1.__proto__ === Person.prototype); //true
Copy the code

Finally, this article describes only a diagram of an instance of a constructor, the prototype object, not a complete prototype chain. You can understand this part, and I’ll draw a complete prototype chain diagram for you to understand when I talk about the prototype chain. Try to understand today’s article first, and draw your own constructors – prototype objects – instances of the relationship diagram, I believe you will gain more.

Finally finally, what I said is not necessarily right, you must try yourself!

(End of article)