The explanation of JavaScript inheritance was agreed, but it has been delayed. Without further ado, just get to the point.
Since you want to understand inheritance, it proves that you already have a certain understanding of JavaScript object-oriented. If you don’t understand anything, you can refer to the Basic Explanation of Object-Oriented JS, Factory Mode, Constructor Mode, Prototype Mode, Mixed Mode, Dynamic Prototype Mode". Next, let’s talk about the inheritance of JavaScript generally through those methods.
Prototype chain
The easiest way to implement inheritance in JavaScript is to use a prototype chain and point the prototype of the child type to an instance of the parent type, that is, "subtype.prototype = new parent type();". The implementation method is as follows:
// Create a constructor function SuperType() { this.name = ['wuyuchang', 'Jack', 'Tim']; this.property = true;}// Add method SuperType.prototype.getSuerperValue = function() { return this.property;}// Create a constructor function SubType() { this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false;}// Key steps to implement inheritance, the prototype of the subtype points to an instance of the parent type SubType.prototype = new SuperType();// Add a method to the child type here. It must be after the inheritance is implemented, otherwise the pointer will be pointed to an instance of the parent type, and the method is empty. SubType.prototype.getSubValue = function() { return this.subproperty;}/* The following is a test code example*/var instance1 = new SubType();instance1.name.push('wyc');instance1.test.push('h5');alert(instance1.getSuerperValue()); // truealert(instance1.getSubValue()); // falsealert(instance1.name); // wuyuchang,Jack,Tim,wycalert(instance1.test); // h1,h2,h3,h4,h5var instance2 = new SubType();alert(instance2.name); // wuyuchang,Jack,Tim,wycalert(instance2.test); // h1,h2,h3,h4You can see that the above code is a simple inheritance implemented through the prototype chain, but there are still some problems in the test code example. I believe that after reading my blog post "Basic Explanation of Object-Oriented JS, Factory Mode, Constructor Mode, Prototype Mode, Mixed Mode, Dynamic Prototype Mode", I must know that the first problem with the prototype chain code is that the prototype of the subtype is an instance of the parent type, that is, the attributes of the parent type contained in the prototype of the subtype, which causes the prototype attributes that reference the type value will be shared by all instances . The instance1.name.push('wyc'); of the above code can prove the existence of this problem. The second problem with the prototype chain is that when creating an instance of a subtype, parameters cannot be passed to the supertype constructor . Therefore, in actual development, we rarely use prototype chains alone.
Borrow constructor
To solve two problems in the prototype chain, developers began to use a technique called borrowing constructors to solve problems in the prototype chain. The implementation idea of this technology is also quite simple. You only need to call the constructor of the parent type within the constructor of the subtype. Don't forget that functions are just objects that execute code in a specific environment, so constructors can be executed through the apply() or call() method . The code is as follows:
// Create a constructor function SuperType(name) { this.name = name; this.color = ['pink', 'yellow']; this.property = true; this.testFun = function() { alert('http://tools.VeVB.COM/'); }}// Add method SuperType.prototype.getSuerperValue = function() { return this.property;}// Create a constructor function SubType(name) { SuperType.call(this, name); this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false;}// Add a method to the subtype here. Be sure to implement inheritance, otherwise the pointer will be pointed to an instance of the parent type, and the method is empty SubType.prototype.getSubValue = function() { return this.subproperty;}/* The following is a test code example*/var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']);instance1.name.push('hello');instance1.test.push('h5');instance1.color.push('blue');instance1.testFun(); // http://tools.VeVB.COM/alert(instance1.name); // wuyuchang,Jack,Nick,hello// alert(instance1.getSuerperValue()); // error alert(instance1.test); // h1,h2,h3,h4,h5 alert(instance1.getSubValue()); // false alert(instance1.color); // pink,yellow,bluevar instance2 = new SubType('wyc');instance2.testFun(); // http://tools.VeVB.COM/alert(instance2.name); // wyc // alert(instance2.getSuerperValue()); // error alert(instance2.test); // h1,h2,h3,h4alert(instance2.getSubValue()); // falsealert(instance2.color); // pink,yellowYou can see that in the above code, the constructor of the subtype SubType in the above code, the inheritance of the attribute is realized by calling the parent type "SuperType.call(this, name);". You can also pass parameters to the parent type when the subtype is created, but a new problem is coming. You can see that I defined a method in the constructor of the parent type: testFun, and a method in the prototype of the parent type: getSuperValue. However, after instantiating the subtype, it is still impossible to call the method getSuperValue defined in the prototype of the parent type , and can only call the method of the constructor in the parent type: testFun. This is the same as using only the constructor mode in creating objects, so that the function has no reusability. Taking these problems into account, the techniques of borrowing constructors are rarely used alone.
Combination inheritance (prototype chain + borrow constructor)
As the name suggests, combination inheritance is a pattern composed of the advantages of combining the use of prototype chains and borrowing constructors. The implementation is also very simple. Since it is a combination, of course it combines the advantages of both parties, namely the prototype chain inheritance method, and the constructor inherits attributes . The specific code is implemented as follows:
// Create a constructor function SuperType(name) { this.name = name; this.color = ['pink', 'yellow']; this.property = true; this.testFun = function() { alert('http://tools.VeVB.COM/'); }}// Add method SuperType.prototype.getSuerperValue = function() { return this.property;}// Create a constructor function SubType(name) { SuperType.call(this, name); this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false;}SubType.prototype = new SuperType();// Add a method to the subtype here. It must be after inheritance is implemented, otherwise the pointer will be pointed to an instance of the parent type, and the method is empty SubType.prototype.getSubValue = function() { return this.subproperty;}/* The following is a test code example*/var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']);instance1.name.push('hello');instance1.test.push('h5');instance1.color.push('blue');instance1.testFun(); // http://tools.VeVB.COM/alert(instance1.name); // wuyuchang,Jack,Nick,helloalert(instance1.getSuerperValue()); // truealert(instance1.test); // h1,h2,h3,h4,h5 alert(instance1.getSubValue()); // false alert(instance1.color); // pink,yellow,bluevar instance2 = new SubType('wyc');instance2.testFun(); // http://tools.VeVB.COM/alert(instance2.name); // wyc alert(instance2.getSuerperValue()); // truealert(instance2.test); // h1,h2,h3,h4alert(instance2.getSubValue()); // falsealert(instance2.color); // pink,yellowThe above code inherits the properties of the parent type through SuperType.call(this, name); and inherits the methods of the parent type through SubType.prototype = new SuperType();. The above code conveniently solves the problems encountered by prototype chains and borrowing constructors, and has become the most commonly used method of instance inheritance in JavaScript. However, the mixed mode is not without its shortcomings. It can be seen that in the above code, the attributes of the parent type have actually been inherited when inheriting the method. However, the reference type is shared at this time. Therefore, the constructor of the parent type is called in the constructor of the child type after the subtype, thus inheriting the attributes of the parent type to overwrite the inherited attributes in the prototype. It is obviously not necessary to call the constructor twice, but is there any way to solve it? When solving this problem, first look at the following two modes.
Prototype inheritance
The implementation method of prototype inheritance is different from that of ordinary inheritance. Prototype inheritance does not use a constructor in the strict sense, but instead uses the prototype to create new objects based on existing objects, and there is no need to create custom types as a result. The specific code is as follows:
function object(o) { function F() {} F.prototype = o; return new F();}Code example:
/* Prototype inheritance*/function object(o) { function F() {} F.prototype = o; return new F();}var person = { name : 'wuyuchang', friends : ['wyc', 'Nicholas', 'Tim']}var anotherPerson = object(person); anotherPerson.name = 'Greg'; anotherPerson.friends.push('Bob');var anotherPerson2 = object(person); anotherPerson2.name = 'Jack';anotherPerson2.friends.push('Rose');alert(person.friends); // wyc,Nicholas,Tim,Bob,RoseParasitic inheritance
/* Parasitic inheritance*/function createAnother(original) { var clone = object(original); clone.sayHi = function() { alert('hi'); } return clone;}Example of usage:
/* Prototype inheritance*/function object(o) { function F() {} F.prototype = o; return new F();} /* Parasitic inheritance*/function createAnother(original) { var clone = object(original); clone.sayHi = function() { alert('hi'); } return clone;}var person = { name : 'wuyuchang', friends : ['wyc', 'Nicholas', 'Rose']}var anotherPerson = createAnother(person); anotherPerson.sayHi();Parasitic combination inheritance
I mentioned earlier the disadvantages of the combination pattern implementation of inheritance in JavaScript. Now let’s solve its shortcomings. The implementation idea is to inherit attributes for constructors, and the mixed form inheritance method of the prototype chain does not need to instantiate the constructor of the parent type when inheriting the method. The code is as follows:
function object(o) { function F() {} F.prototype = o; return new F();}/* Parasitic combination inheritance*/function inheritPrototype(subType, superType) { var prototype = object(superType.prototype); prototype.constructor = subType; subType.prototype = prototype;}When using it, you only need to replace the line of code "SubType.prototype = new SuperType();" in the combination mode with inheritPrototype(subType, superType);. The efficiency of parasitic combinatorial inheritance is reflected in that it calls the parent type constructor only once, avoiding the creation of unnecessary or redundant properties. At the same time, the prototype chain can remain unchanged, so instanceof and isPrototypeof() can also be used normally. This is also the most ideal inheritance method at present, and it is currently transforming to this model. (YUI also uses this mode.)
This blog post refers to "JavaScript Advanced Programming 3rd Edition". The code is rewritten and more specific, and commented to make it easier for everyone to understand. If you have unique insights into JS inheritance, don’t be stingy. Reply to your opinions for your reference!