If you really can't understand some knowledge at that time, you can let it go for the time being and leave it to the future and maybe you can understand it.
A few months ago, I was holding "JavaScript Advanced Programming (Third Edition)" and after chewing on creating the object, I started to chew on inheritance. However, after chewing on the prototype chain, I really couldn't stand it anymore, and my mind became more and more messy, so I threw it aside and continued to look at the latter one. Now that I have used this summer vacation to understand this inheritance, I will sort out my notes.
Prototype Chaining
Let’s read an article first. The author of the article is very good and is equipped with high-definition pictures. lol…
Link: [Study Notes] View the JS prototype chain from a small perspective
A few words from the original text
Determine the relationship between prototype and instance
There are two ways to detect the relationship between a prototype and an instance:
instanceof: determines whether the object is an instance of another object
The internal computing mechanism of instanceof is as follows:
functioninstance_of(L, R){//L represents the left expression, R represents the right expression varO = R.prototype;// Take the display prototype of R L = L.__proto__; // Take the implicit prototype of L while(true) {if(L ===null)returnfalse; if(O === L)// Here the point: When O is strictly equal to L, return truereturntrue; L = L.__proto__; } }The above code is excerpted from: In-depth analysis of the JavaScript instanceof operator
isPrototypeOf(): Tests whether an object exists on the prototype chain of another object
Please refer to the differences between these two methods: JavaScript isPrototypeOf vs instanceof usage
Only use prototype chain to achieve inheritance
Disadvantages: 1. The prototype attributes referring to the type value will be shared by the instance; 2. When creating an instance of a subtype, parameters cannot be passed to the supertype constructor.
functionFather(){this.name ="father";this.friends = ['aaa','bbb'];}functionSon(){}Son.prototype = newFather();Son.prototype.constructor = Son;vars1 = newSon();vars2 = newSon();console.log(s1.name);// fatherconsole.log(s2.name);// fathers1.name = "son";console.log(s1.name);// sonconsole.log(s2.name);// fatherconsole.log(s1.friends);// ["aaa", "bbb"]console.log(s2.friends);// ["aaa", "bbb"]s1.friends.push('ccc','ddd');console.log(s1.friends);// ["aaa", "bbb", "ccc", "ddd"]console.log(s2.friends);// ["aaa", "bbb", "ccc", "ddd"]Only use constructors to achieve inheritance
Implementation method: Call the supertype constructor inside the subtype constructor (using the apply() and call() methods)
Advantages: Solve the problem of referencing type attributes in the prototype, and subclasses can pass parameters to superclasses
Disadvantages: Subclass instances cannot access the methods defined in the parent class (superclass) prototype, so there is no way to talk about function reuse.
functionFather(name,friends){this.name = name;this.friends = friends;}Father.prototype.getName = function(){returnthis.name;};functionSon(name){// Note: To ensure that the Father constructor does not override the properties of the Son constructor, place the code that calls the Father constructor before the properties defined in Son. Father.call(this,name,['aaa','bbb']);this.age =22;}vars1 =newSon('son1');vars2 =newSon('son2');console.log(s1.name);// son1console.log(s2.name);// son2s1.friends.push('ccc','ddd');console.log(s1.friends);// ["aaa", "bbb", "ccc", "ddd"]console.log(s2.friends);// ["aaa", "bbb"]// Subclass instance cannot access the method s1.getName() in the parent class prototype; // TypeError: s1.getName is not a functions2.getName(); // TypeError: s2.getName is not a functionCombination Inheritance
Implementation method: Use the prototype chain to implement inheritance of prototype properties and methods, and use the constructor to implement inheritance of instance properties.
functionFather(name,friends){this.name = name;this.friends = friends;}Father.prototype.money = "100k $";Father.prototype.getName = function(){console.log(this.name);};functionSon(name,age){// Inherit the property of the parent class Father.call(this,name,['aaa','bbb']);this.age = age;}// Inherit the properties and methods in the parent class prototype Son.prototype = newFather();Son.prototype.constructor = Son;Son.prototype.getAge = function(){console.log(this.age);};vars1 =newSon('son1',12);s1.friends.push('ccc');console.log(s1.friends);// ["aaa", "bbb", "ccc"]console.log(s1.money);// 100k $s1.getName(); // son1s1.getAge(); // 12vars2 =newSon('son2',24);console.log(s2.friends);// ["aaa", "bbb"]console.log(s2.money);// 100k $s2.getName(); // son2s2.getAge(); // 24Combination inheritance avoids the defect of unilaterally using prototype chains or constructors to implement inheritance, combines their advantages, and becomes the most commonly used inheritance model in JavaScript, but it is also flawed, and the defect of combination inheritance will be specifically mentioned later.
Prototypal Inheritance
Implementation idea: Use prototypes to create new objects based on existing objects, without creating custom types because of this.
To achieve this, the following function (obj) is introduced
functionobj(o){functionF(){} F.prototype = o;returnnewF();}varperson1 = { name: "percy", friends: ['aaa','bbb']};varperson2 = obj(person1);person2.name = "zyj";person2.friends.push('ccc');console.log(person1.name);// percyconsole.log(person2.name);// zyjconsole.log(person1.friends);// ["aaa", "bbb", "ccc"]console.log(person2.friends);// ["aaa", "bbb", "ccc"]ECMAScript 5 Normalizes prototype inheritance by adding the Object.create() method. In the case of passing in a parameter, the Object.create() and obj() methods behave the same. varperson1 = { name: "percy", friends: ['aaa','bbb']};varperson2 =Object.create(person1);person2.name = "zyj";person2.friends.push('ccc');console.log(person1.name);// percyconsole.log(person2.name);// zyjconsole.log(person1.friends);// ["aaa", "bbb", "ccc"]console.log(person2.friends);// ["aaa", "bbb", "ccc"]This inheritance can be chosen when there is no need to mobilize the constructor to create it, but just want one object to remain similar to another.
Parasitic Inheritance
Parasitic inheritance is an idea closely related to prototype inheritance.
Implementation idea: Create a function that is only used to encapsulate the inheritance process, which internally enhances the object in some way and finally returns the object.
functionobj(o){functionF(){} F.prototype = o;returnnewF();}functioncreatePerson(original){// Encapsulate inheritance process varclone = obj(original);// Create object clone.showSomething = function(){// Enhance object console.log("Hello world!"); };returnclone;// Return object}varperson = { name: "percy"};varperson1 = createPerson(person);console.log(person1.name);// percyperson1.showSomething(); // Hello world!Parasitic Combination Inheritance
Let’s first talk about the shortcomings of our previous combination inheritance. The biggest problem with combination inheritance is that no matter what the situation is, the constructor of the parent class will be called twice: one is when creating the prototype of the subclass, and the other is when calling the subclass constructor, the constructor of the parent class is called inside the subclass constructor.
functionFather(name,friends){this.name = name;this.friends = friends;}Father.prototype.money = "100k $";Father.prototype.getName = function(){console.log(this.name);};functionSon(name,age){// Inherit the property of the parent class Father.call(this,name,['aaa','bbb']);// The second call to Father() is actually called this.age = age;}// Inherit the properties and methods in the parent class prototype Son.prototype = newFather();// The first time Father() is called Son.prototype.constructor = Son;The first call makes the prototype of the subclass an instance of the parent class, so that the prototype of the subclass obtains the instance attribute of the parent class; the second call will cause the instance attribute of the subclass to also obtain the instance attribute of the parent class; and the instance attribute of the subclass will block the attributes that are duplicated with the subclass prototype by default. Therefore, after these two calls, unnecessary attributes appear in the subclass prototype, thus introducing parasitic combination inheritance to solve this problem.
The idea behind parasitic combination inheritance is: There is no need to call the parent class constructor to specify the prototype of the subclass. All we need is a copy of the parent class prototype.
Essentially, it is to use parasitic inheritance to inherit the prototype of the parent class, and then return the result to the prototype of the child class.
functionobj(o){functionF(){} F.prototype = o;returnnewF();}functioninheritPrototype(son,father){varprototype = obj(father.prototype);// Create object prototype.constructor = son; // Enhance object son.prototype = prototype; // Return object}functionFather(name,friends){this.name = name;this.friends = friends;}Father.prototype.money = "100k $";Father.prototype.getName = function(){console.log(this.name);};functionSon(name,age){// Inherit the property of the parent class Father.call(this,name,['aaa','bbb']); this.age = age;}// Inherit the properties and methods in the parent class prototype inheritPrototype(Son,Father);Son.prototype.getAge = function(){console.log(this.age);};vars1 =newSon('son1',12);s1.friends.push('ccc');console.log(s1.friends);// ["aaa", "bbb", "ccc"]console.log(s1.money);// 100k $s1.getName(); // son1s1.getAge(); // 12vars2 =newSon('son2',24);console.log(s2.friends);// ["aaa", "bbb"]console.log(s2.money);// 100k $s2.getName(); // son2s2.getAge(); // 24Advantages: Make subclass prototypes avoid inheriting unnecessary instance properties in parent class.
Developers generally believe that parasitic combinatorial inheritance is the most ideal inheritance method based on type inheritance.
at last
Finally, I highly recommend two very hard articles
Javascript How Prototypal Inheritance really works
JavaScript's Pseudo Classical Inheritance diagram (need to cross the wall)
Take a hard picture from the second article:
After reading it, I understand the prototype chain in seconds. Is there anything?
The above is the collection of the information inherited by JavaScript. We will continue to add relevant information in the future. Thank you for your support for this website!