inheritance

Inheritance comes in many ways

The first type: prototype chain inheritance

Prototype chain inheritance is one of the more common inheritance methods. There is a triangular relationship among the constructors, prototypes and instances involved. That is, each constructor has a prototype object “constructor” and the prototype object contains a pointer to the constructor “constructor”. Then the instance contains a pointer to an implicit prototype object. “__ proto __ is called an implicit prototype. I want to make a distinction just to help you understand, sorry, because of Markdown syntax, __ proto __ has Spaces.”

function Parent1() { this.name = 'parent1'; this.play = [1, 2, 3] } function Child1() { this.type = 'child1'; } Child1.prototype = new Parent1(); console.log(new Child1()); var s1 = new Child1() var s2 = new Child1() s1.play.push(4) console.log(s1.play, S2.play) // [1,2,3,4] [1,2,3,4] but there is a drawback, the object of stereotype inheritance is only a reference, so each instance can be modified, this is a drawback of using stereotype chain inheritance. Prototype = new Parent1() = new Parent1(); Since obj.__proto__ = object.create (constructive.protype) when we use the new keyword, this is equivalent to copying the Object, so the following constructor changes to the prototype make little sense. Because the point has changed.Copy the code

Refer to what I wrote earlier where new is in the middle

Second: constructor inheritance (with call/apply)

function Parent2(){ this.name = 'parent2'; } Parent2.prototype.getName = function () { return this.name; } function Child2(){ Parent2.call(this); this.type = 'child2' } let child = new Child2(); console.log(child); // No problem console.log(child.getname ()); Parent2: Parent2: Parent2: Parent2: Parent2: Parent2: Parent2: Parent2: Parent2 The problem is that you can only inherit the instance attributes and methods of the parent class, not the prototype attributes or methods. The above two inheritance methods have their own advantages and disadvantages, so combining the advantages of the two, the following combination inheritance method is generated.Copy the code

Third: Combinatorial inheritance (the first two combinations)

function Parent3 (age) { this.name = 'parent3'; this.play = [1, 2, 3]; this.age = age } Parent3.prototype.getName = function () { return this.name; Parent3() parent3.call (this,30);} function Child3() {Parent3() parent3.call (this,30); this.type = 'child3'; } // call Parent3() child3. prototype = new Parent3(30); / / hang up the constructor manually, pointing to his own constructor Child3. The prototype. The constructor = Child3; var s3 = new Child3(); var s4 = new Child3(); s3.play.push(4); console.log(s3.play, s4.play); Console.log (s3.getName()); // Output 'parent3' console.log(s4.getName()); // Normal output 'parent3' adds a new problem: Parent3 (Child3, Child3, Child3); Parent3 (Child3, Child3, Child3, Child3, Child3); This is not what we want to see. There is also a more detailed problem with the second call to Parent3. The property of Parent3 is repeated at different levels. The age of Parent3 will also be on the first level object of the instance, and the "redundant" property will also follow the rules of the prototype chain. In some cases, however, this can cause an error, such as when the age attribute is removed from the instance and is actually still accessible, and the attribute is retrieved from the stereotype.Copy the code

Fourth: original type inheritance

let parent4 = { name: "parent4", friends: ["p1", "p2", "p3"], getName: function() { return this.name; }}; let person4 = Object.create(parent4); person4.name = "tom"; person4.friends.push("jerry"); let person5 = Object.create(parent4); person5.friends.push("lucy"); console.log(person4.name); // tom console.log(person4.name === person4.getName()); // tom === tom ===> tom console.log(person5.name); // parent4 console.log(person4.friends); // ["p1", "p2", "p3",'jerry','lucy'] console.log(person5.friends); // ["p1", "p2", "p3",' Jerry ',' Lucy '] This inheritance method has the disadvantage of copying object references, which may cause the object to be modified.Copy the code

Fifth: parasitic inheritance

The method of inheritance is called parasitic inheritance, in which a shallow copy of the target object is obtained using the original inheritance, and then the power of the shallow copy is enhanced by adding some methods.

Although it has the same advantages and disadvantages as original inheritance, parasitic inheritance still adds more methods to the parent class than original inheritance for common object inheritance. So let’s see how the code works, right

let parent5 = { name: "parent5", friends: ["p1", "p2", "p3"], getName: function() { return this.name; }}; function clone(original) { let clone = Object.create(original); clone.getFriends = function() { return this.friends; }; return clone; } let person5 = clone(parent5); console.log(person5.getName()); console.log(person5.getFriends());Copy the code

The sixth kind: parasitic combinatorial inheritance

We combine combinatorial inheritance and parasitic inheritance to obtain the parasitic combinatorial inheritance, which is also the relatively optimal inheritance among all inheritance methods. The code is as follows.

function Parent6() { this.name = 'parent6'; this.play = [1, 2, 3]; } Parent6.prototype.getName = function () { return this.name; } function Child6() { Parent6.call(this); this.friends = 'child6'; } function clone (parent, Prototype = object.create (parent. Prototype); child.prototype.constructor = child; } clone(Parent6, Child6); Child6.prototype.getFriends = function () { return this.friends; } let person6 = new Child6(); console.log(person6); console.log(person6.getName()); console.log(person6.getFriends()); // It can solve the problem of composite inheritance parent being called twice and property repeating at different levels.Copy the code

The extends keyword of ES6 implements logic

Using the extends sugar in ES6, it’s easy to implement JavaScript inheritance directly with keywords, but if you want to understand how extends sugar is implemented, you have to dig into the underlying logic of extends.

Class Person {constructor(name) {this.name = name} class Person {constructor(name) {this.name = name getName() {... } getName = function () { console.log('Person:', this.name) } } class Gamer extends Person { constructor(name, Age) {// If there is a constructor in a subclass, you need to call super() first before using "this". Super (name) this.age = age}} const juiceice = new Gamer('juiceice', 20) juiceice.getName() // Successfully access the method of the parent classCopy the code

Because of browser compatibility issues, if you encounter a browser that does not support ES6, you will need to use Babel to compile ES6 code into ES5, so that some browsers that do not support the new syntax can run.

function _possibleConstructorReturn (self, call) { // ... return call && (typeof call === 'object' || typeof call === 'function') ? call : self; } function _inherits (subClass, Prototype = Object. Create (superClass && superClass. Prototype, {constructor: {value: //) {constructor: {value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var Parent = function Parent () {this _classCallCheck(this, Parent); }; var Child = (function (_Parent) { _inherits(Child, _Parent); function Child () { _classCallCheck(this, Child); return _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).apply(this, arguments)); } return Child; }(Parent)); As can be seen from the compiled source code above, it also adopts the parasitic combination inheritance method, so it also proves that this method is a better way to solve inheritance.Copy the code

conclusion

Object. Create is used to divide the different inheritance methods. Finally, parasitic combinatorial inheritance is the optimal inheritance method modified by combinatorial inheritance.

If you don’t understand anything, or if there are any inadequacies or mistakes in my article, please point them out in the comments section. Thank you for reading.