On prototype and prototype chain

Keywords: Javascript

Understanding prototypes and prototype chains

This article will use concepts + exercises to help understand

concept

Before we understand the prototype, let's talk about constructors and using constructors to create objects

Constructor and create instance

for instance:

An ordinary Person function is defined, which is still an ordinary function at this time

function Person(name,age) {
    this.name = name,
    this.age = age,
    this.sayName = function(){
        console.log(this.name)
    }
}

I'll do this at this time

var p1 = new Person('zhangsan',18);

At this point, the Person function is not an ordinary function, but a constructor. And instantiates an object p1

The instantiated object p1 will have the properties and methods of the constructor.

Here is a direct question. Why does an object be created after the Person function is new, and the object also has the properties and methods of the constructor Person.

Here we have to mention the steps to be performed after the new operation:

1. Created an object

var obj = new Object();

2. Add the new object's__ proto__ prototype pointing to constructor

obj.__proto__ = Person.prototype

3. Point this in the constructor to

Person.call(obj)

This is why this.name = name is used in the constructor to create different objects. This always points to the created object.

4. Execute the code in the constructor

5. If the constructor returns an object, it returns the modified object, otherwise it returns a new object

After understanding the process of creating objects, let's talk about the disadvantages of a constructor.

for instance:

//Use the code example just now
function Person(name,age) {
    this.name = name,
    this.age = age,
    this.sayName = function(){
        console.log(this.name)
    }
}
//Create two objects
var p1 = new Person('zhangsan',18)
var p2 = new Person('lisi',20)
//Judge whether the functions of two objects are the same
console.log(p1.sayName == p2.sayName)//false

Look at the above example to explain why the method defined in the constructor will be created once when creating each instance, so why two methods have the same name but are not equal. Therefore, in order to optimize this disadvantage, we have to define attributes and methods separately.

At this time, go directly to the prototype.

Prototype and prototype chain

We just said that if the constructor defines a method, there will be some disadvantages, so we will use the prototype to solve this disadvantage

So what is the prototype?

Each function creates a prototype attribute, which is an object containing attributes and attributes that should be shared by instances of a specific reference type

method. In fact, this object is the prototype of the object created by calling the constructor. The advantage of using a prototype object is that it is defined on top of it

Properties and methods can be shared by object instances. Originally, the values directly assigned to object instances in the constructor can be directly assigned to their prototypes.

To put it simply:

The prototype is another storage space of the constructor. The object properties of the instantiated object inherit from the constructor, and the methods inherit the prototype.

The constructor. Prototype is the prototype object

for instance:

function Person(name,age) {
   this.name = name
   this.age = age
}
Person.prototype.sayName = function() {
     console.log('I am the name of the method output object on the prototype:' + this.name)
}
var person1 = new Person('Zhang San',18)
var person2 = new Person('Li Si',28)
console.log(person.name)
console.log(person.age)
console.log(person1.sayName == person2.sayName)//true solves the disadvantages of constructors.
person.sayName()

In the above example, a method is defined in the Person constructor and a method sayName is defined in the Person prototype

The name age attribute of the object is output and the sayName method is called

Here, some people may wonder that the name and age can be output because they are defined in the constructor, but how to call the sayName method is not defined in the constructor

Prototype chain

Here I will lead to three properties__ proto__ constructor prototype

Let me draw a diagram to let you understand the relationship between these three attributes

Can know

__ proto__ Is a property pointer in the object that can point to Person.prototype

A constructor is a property in an object that can point to a constructor

Prototype is a constructor. Prototype is a prototype

After looking at the figure, we can see why the person object can call the method sayName that is not defined by the constructor

person will find the method it wants to call similar to the chain scope search. This chain search can be understood as the prototype chain. In the figure, it is only a small part of the prototype chain.

After reading the above concepts, you may not quite understand the concepts of prototype and prototype chain. Let's do exercises directly to deepen our understanding.

exercises

Example 1:

function Fn() {
    this.x = 100;
    this.y = 200;
    this.getX = function () {
        console.log(this.x);
    }
}
Fn.prototype.getX = function () {
    console.log(this.x);
};
Fn.prototype.x = 20
Fn.prototype.getY = function () {
    console.log(this.y);
};
let f1 = new Fn();
let f2 = new Fn();

console.log(f1.getX === f2.getX);
console.log(f1.getY === f2.getY);
console.log(f1.__proto__.getY === Fn.prototype.getY);
console.log(f1.__proto__.getX === f2.getX);
console.log(f1.getX === Fn.prototype.getX);
console.log(f1.constructor);
console.log(Fn.prototype.__proto__.constructor);
f1.getX();
f1.__proto__.getX();
f2.getY();
Fn.prototype.getY();

Explanation:

console.log(f1.getX === f2.getX); 1
console.log(f1.getY === f2.getY); 2

1: F1 and f2 are two different objects, so creating these two objects is equivalent to creating two methods with different constructors. The disadvantage of creating getX constructors is that creating each object will create one for each object

1 is false

2: the above concept says that the methods in the prototype are public, so you don't have to create another method for an object

2 is true

console.log(f1.__proto__.getY === Fn.prototype.getY); 3
console.log(f1.__proto__.getX === f2.getX); 4
console.log(f1.getX === Fn.prototype.getX); 5
console.log(f1.constructor); 6
console.log(Fn.prototype.__proto__.constructor); 7

3 : f1.__proto__ It is the prototype object pointing to Fn that gets the method getY in Fn.prototype, so it is true

4 : f1.__proto__ Is to point to the prototype object of Fn and obtain the method getX in Fn.prototype,

The method getX in getX comes from the constructor instance, so the two different methods are false

5: similar to 4, false

6: the constructor of F1 is Fn

7 : Fn.prototype.__proto__ Here is the prototype pointing to the FN prototype. The prototype is Object.prototype. In fact, it is equivalent to asking the constructor Object of Object.prototype

f1.getX(); 8
f1.__proto__.getX(); 9
f2.getY(); 10 
Fn.prototype.getY(); 11

8: call getX in the instantiated object. The answer is 100

10: there is no getY in the instantiated object here. You can only find the getY and this call on the prototype. Who calls to whom, so the answer is 200

9 : f1.__proto__ It is equivalent to Fn.prototype call. this points to x on the problem prototype, so it is 20

11: FN. Prototype. Gety() this points to the problem. If there is no y on the prototype, it outputs undefined

Summary:
1. First understand the new process of creating constructor
2. Clarify the difference between constructor definition method and prototype constructor
3. Three attributes__ proto__ constructor prototype relationship
4. You can draw your own picture to understand
If there are any mistakes above, please correct them and learn love & & peace together

Posted by macman90 on Fri, 03 Sep 2021 19:02:52 -0700