Six JavaScript inheritance methods and their pros and cons
Tips: To better understand JS inheritance, you must understand constructors, prototype objects, instantiated objects, prototype chains and other concepts
To understand JS inheritance, we first need to understand the stereotype chain: every instance object has a proto property (implicit stereotype), which is used to find the stereotype chain within JS; Each constructor has a prototype property that displays the prototype, instance, of the modified object. The characteristics of prototype chain are: through the instance. Proto to find the attributes on the prototype, from the subclass up to find the attributes of the object prototype, and then form a search chain, namely the prototype chain.
The first type: prototype chain inheritance
Make use of the characteristics of the prototype chain for inheritance
Function Parent(){this.name = 'web '; this.type = ['JS','HTML','CSS']; } Parent.prototype.Say=function(){ console.log(this.name); } function Son(){}; Son.prototype = new Parent(); son1 = new Son(); son1.Say();Copy the code
The above examples explain: Create a constructor called Parent (let’s call it the Parent constructor) with two properties name and type. Set the Say method using the Parent constructor’s properties (the prototype object). Parent has two properties and one method. Moment is called the child constructor (4) set Son attribute (i.e., a prototype object) values for Parent instance constructor of the Parent object, namely the child constructor Son inherited the Parent constructor Parent, the Son also has two attributes and a method (5) to instantiate the Son constructor, the assignment to the variable son1, Son1 is an instantiated object with 2 attributes and 1 method. ⑥ Output son1’s Say method, which results in “web front-end “. Because Son. Prototype inherits the Parent instantiation object, all Son instantiations are the same and share the properties and methods of the prototype object. The code is as follows:
son1 = new Son(); son2 = new Son(); son1.type.push('VUE'); console.log(son1.type); //['JS','HTML','CSS','VUE'] console.log(son2.type); //['JS','HTML','CSS','VUE']Copy the code
Son1, son2 are [‘ JS ‘, ‘HTML’, ‘CSS’, ‘VUE’]
Second: constructor inheritance
Inheriting through the constructor call method, let’s look at the code directly:
Function Parent(){this.name = 'web '; this.type = ['JS','HTML','CSS']; } function Son(){ Parent.call(this); } son1 = new Son(); son1.type.push('VUE'); console.log(son1.type); //['JS','HTML','CSS','VUE'] son2 = new Son(); console.log(son2.type); //['JS','HTML','CSS']Copy the code
The above examples explain: 1) create Parent constructor Parent, there is the name, type, two attributes (2) create a class constructor Son, function through the internal call method to invoke the Parent constructor Parent, implementation inheritance (3) to create a constructor respectively Son of two son1, son2 instantiate objects, Son1 type attribute added elements, son2 did not add, the result is different, indicating the implementation of independent advantages: ① implementation of instantiation object independence; ② You can also add parameters to the instantiated object
function Parent(name){ this.name = name; } function Son(name){ Parent.call(this,name); } son1 = new Son('JS'); console.log(son1); //JS son2 = new Son('HTML'); console.log(son2); //HTMLCopy the code
The call method only calls the attributes and methods of the parent constructor, and does not call the methods of the parent constructor prototype object
The third is combinatorial inheritance
Take advantage of the respective advantages of stereotype chain inheritance and constructor inheritance to combine them, again looking at the code:
function Parent(name){ this.name = name; this.type = ['JS','HTML','CSS']; } Parent.prototype.Say=function(){ console.log(this.name); } function Son(name){ Parent.call(this,name); } Son.prototype = new Parent(); Son1 = new Son(' son2 '); Son2 = new Son(' son2 '); son1.type.push('VUE'); son2.type.push('PHP'); console.log(son1.type); //['JS','HTML','CSS','VUE'] console.log(son2.type); //['JS','HTML','CSS','PHP'] son1.Say(); / / zhang SAN son2. Say (); / / li siCopy the code
The above examples explain: Create a Parent constructor with two attributes name, type, and Say. Parent has two attributes and one method, and Parent has two attributes and one method. Function within the call from the method call Parent constructor Parent, implementation inheritance (4) the child constructor Son inherits the father Parent constructor, the Son also has two attributes and a method (5) create a constructor Son respectively two son1, son2 instantiate objects, Pass different parameters, add different elements to type attribute, call prototype object Say method advantages: ① use prototype chain inheritance to achieve prototype object method inheritance ② use constructor inheritance to achieve attribute inheritance, and parameter combination function basically meet JS inheritance, more common disadvantages: In any case, the parent constructor is called twice: once when the child prototype is created and once inside the child constructor
Fourth: original type inheritance
Create a function that takes arguments as a prototype object of an object
function fun(obj) { function Son(){}; Son.prototype = obj; return new Son(); } var son1 = fun(parent); var son2 = fun(parent); console.log(son1.name); / / zhang SAN console. The log (son2. Name); / / zhang SANCopy the code
Example: ① Create a function fun, internally define a constructor Son ② set Son’s prototype object as a parameter, the parameter is an object, complete inheritance ③ instantiate Son, return an instantiated object advantages and cons: similar to the prototype chain
Fifth: parasitic inheritance
On the basis of the original type inheritance, enrich the object inside the function
function fun(obj) { function Son() { }; Son.prototype = obj; return new Son(); } function JiSheng(obj) { var clone = fun(obj); Clone.Say = function () {console.log(' I'm adding methods '); } return clone; } var parent = {name: 'parent'} var parent1 = JiSheng(parent); var parent2 = JiSheng(parent); console.log(parent2.Say==parent1.Say); // falseCopy the code
The above examples explain: ① On the basis of the original inheritance, a JiSheng function was added. ② The object returned by fun was enhanced and the new Say method was added. Finally, ③ called JiSheng function twice, assigning values to variables parent1 and parent2 respectively. The result is false, the advantages and disadvantages of implementation independence: similar to constructor inheritance, call a function once must create a method, cannot achieve function reuse, low efficiency
As a bonus, ES5 has a new method called Object.create() that encapsulates the original type inheritance. This method can take two arguments: the first is the new object’s prototype (optional), and the second is the new object’s new attribute, so the above code could also look like this:
function JiSheng(obj) { var clone = Object.create(obj); Clone.Say = function () {console.log(' I'm adding methods '); } return clone; } var parent = {name: 'parent'} var parent1 = JiSheng(parent); var parent2 = JiSheng(parent); console.log(parent2.Say==parent1.Say); // falseCopy the code
Sixth: parasitic combination inheritance
Using the combination of inheritance and parasitic inherit to the respective advantage combination method we have already said, its disadvantage is that the two call parent constructor, in creating the child archetype, another is in the child inside a constructor, so we only need to optimize this problem, which reduced a call the parent class constructor, just using the parasitic inherited feature, Create child stereotypes by inheriting the stereotypes of the parent constructor.
function JiSheng(son,parent) { var clone = Object.create(parent.prototype); // create object son.prototype = clone; Clone. Constructor = son; } function Parent(name){this.name = name; this.type = ['JS','HTML','CSS']; } Parent.prototype.Say=function(){ console.log(this.name); } function Son(name){ Parent.call(this,name); } JiSheng(Son,Parent); Son1 = new Son(' son2 '); Son2 = new Son(' son2 '); son1.type.push('VUE'); son2.type.push('PHP'); console.log(son1.type); //['JS','HTML','CSS','VUE'] console.log(son2.type); //['JS','HTML','CSS','PHP'] son1.Say(); / / zhang SAN son2. Say (); / / li siCopy the code
The above examples explain: Create () to clone the prototype of the parent constructor into a clone. ③ Add the constructor attribute to the prototype of the child constructor. ④ Add the constructor attribute to the prototype. Because the modification of the prototype in the third leads to the loss of the default attribute advantages and disadvantages of the copy: the advantages of combination inheritance, the advantages of parasitic inheritance, currently JS inheritance is used in this inheritance method