Long time no blog, hehe, this month is the last one months of 2017, we should all start to write the year-end summary of it, hehe, Xiao Ying today to share the next JavaScript in several ways of inheritance and their advantages and disadvantages.
1. Implementing inheritance with constructors
Principle: Modify this point by the call () function to mount the parent class attribute to the subclass instance.
function parent1 () { this. Name = ' Parent1 '; } function child1 () { Parent1.call (this); this. Type = ' Child1 '; } Console.log (new child1);
Printing results:
When we add the say method to the prototype property of the parent class parent1, it is not available in child1.
function parent1 () { this. Name = ' Parent1 '; } function () { console.log (' hello '); }; function child1 () { Parent1.call (this); this. Type = ' Child1 '; } Console.log (newnew child1 (). Say ());
Printing results:
So. With the help of constructors, only partial inheritance can be implemented, and if the parent property is in the constructor, all inheritance is possible, and if there are methods on the parent prototype object, the subclass is not inherited.
Summarize:
Advantages:
1. The constructor of the parent class is called only once, avoiding unnecessary and unnecessary attributes being created on the subclass prototype.
2. The prototype chain remains unchanged.
Disadvantage: Only partial inheritance can be implemented, and if the parent property is in the constructor, all inheritance can be implemented, and if there are methods on the parent prototype object, the subclass is not inherited.
2. Using the prototype chain for inheritance (the most common way)
Principle: Assigning the prototype property of a subclass to the parent class instance object, the _proto_ property of the subclass inherits the parent class.
functionParent2 () { This. Name = ' Parent2 '; This. play = [1, 2, 3]; } Parent2.prototype.say=function() {Console.log (' Hello '); }; functionchild2 () { This. Type = ' Child2 '; } Child2.prototype=NewParent2 (); Console.log (Newchild2); varP1 =Newchild2 (); varP2 =Newchild2 (); Console.log (P1.say ()); Console.log (P1.play, P2.play); P1.play.push (4); Console.log (P1, p2); Console.log (P1.play, p2.play);
Printing results:
Attention:
1. In the first inheritance mode, subclasses are not inheriting the contents of the parent Class prototype property, but can now inherit.
2. In fact, Xiao Ying only performed P1.play.push (4), however the value of P2.play also changed.
child2.prototype = new Parent2 (), their __proto__ inherit the parent class Span style= "color: #000000;" >parent2 all properties of the . Although superficially p1.play.push (4 looks like it only changed the P1 Play property, but it actually changed the parent class < Span style= "color: #000000;" >parent2 The play property of , while P1,p2 inherits the parent2, so P1, P2 change at the same time.
Summary:
Advantage: The method of the parent class (GetName) has been reused.
Disadvantage: The prototype of the overridden subclass equals one instance of the parent class (the parent class's instance property becomes the prototype property of the subclass) if the parent class contains a property of a reference type, all instances of the subclass share the property (the * prototype * property that contains the reference type is shared by the instance).
3. Combination method
functionParent3 () { This. Name = ' Parent3 '; This. play = [1, 2, 3]; } functionchild3 () {Parent3.call ( This); This. Type = ' child3 '; } Child3.prototype=NewParent3 (); varP3 =Newchild3 (); varP4 =Newchild3 (); Console.log (P3.play, P4.play); P3.play.push (4); Console.log (P3,P4); Console.log (P3.play, p4.play);
Printing results:
Attention:
In the above results, we have found that the same only to P3.play.push (4), but only P3 a change, but P4 did not change, in fact, everyone through the small red box up the place, big will understand, why P3, P4 __proto__ inherited the attributes of the parent class Parent2, and why the P3,P4 was modified, but the P4 did not change.
Summary:
Advantages: Inherit the advantages of the above two methods, discard the shortcomings, reuse the method, the subclass has its own properties.
Disadvantage: Because the parent class constructor is executed two times, the child class's prototype object (Sub.prototype) also has an instance property of the parent class, and these properties are overwritten with the properties of the class instance (SUB1,SUB2), and there is a memory waste.
4. Optimization of combinatorial inheritance 1
functionparent4 () { This. Name = ' Parent4 '; This. play = [1, 2, 3]; } functionChild4 () {Parent4.call ( This); This. Type = ' Child4 '; } Child4.prototype=Parent4.prototype; varP5 =NewChild4 (); varP6 =NewChild4 (); Console.log (P5, p6); Console.log (P5instanceofChild4, p5instanceofparent4); Console.log (p5.constructor);
Printing results:
Attention:
Both instanceof and constructor are used to determine whether an instance object is an instance of this constructor.
The difference is: with constructor more rigorous than instanceof , for example, if A inheritance b,b inherit C,a generated instance object, with instanceof to determine the relationship with a, B, C, is true. So it is not possible to distinguish between A, B, C who generates an instance. The constructor is a property of the prototype object, and the value of this property is pointed to the object that created the current instance.
Console.log (P5 instanceof Child4, p5 instanceof parent4); The result is the same, and P5.constructor is not child4 but parent4.
5. Combinatorial inheritance optimization 2--parasitic combined inheritance
functionparent5 () { This. Name = ' PARENT5 '; This. play = [1, 2, 3]; } functionchild5 () {Parent5.call ( This); This. Type = ' Child5 '; } Child5.prototype=object.create (Parent5.prototype); Child5.prototype.constructor=Child5; varP7 =Newchild5 (); varP8 =Newchild5 (); Console.log (P7, P8); Console.log (p7.constructor);
Printing results:
Summarize:
The disadvantage of combinatorial inheritance is that the parent class constructor is called when the parent class method is inherited, resulting in memory wastage and the actual constructor of the instance object cannot be found.
When reusing the parent method, the Object.create method can also be used to achieve the goal, without calling the parent class constructor, and assigning the Prototype.constructor property of the subclass to itself, then the problem is solved perfectly.
JavaScript various inheritance and pros and cons