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