Hunzi front-end know about JS six kinds of inheritance

Inheritance is a concept OO language most talked about. Many OO languages ​​supports two types of inheritance: interface inheritance and implementation inheritance. Interface inheritance inherit only the method signature, but the actual method implementation inheritance is inherited.

--- This article excerpt "JavaScript Advanced Programming (3rd Edition)"


Since the function is not signed, it can not be achieved in ECMAScript interface inheritance. ECMAScirpt only supports implementation inheritance and implementation inheritance mainly depends on its prototype chain to achieve.

Prototype chain

ECMAScript is described as the main chain of the prototype implemented method inheritance.

The basic idea: use the prototype to make a reference type inherits from another type of reference properties and methods.

PS: Each constructor has a prototype object, the prototype object contains a pointer pointing to the constructor, and examples all contain a pointer to the prototype object.

If so prototype object instance is equal to another type, in which case the prototype object contains a pointer pointing to another prototype, the prototype also contain other a pointer pointing to another constructor. Another example is the prototype of another type, such progressive layers to form a chain and the prototype example.

JS code:

function SuperType(){
    this.property = true;
};
SuperType.prototype.getSuperValue = function(){
    return this.property;
};

function SubType(){
    this.subproperty = false;
}
// 继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
    return this.subproperty;
};

var instance = new SubType();
alert(instance.getSuperValue());    // true

复制代码

Above code defines two types: Supertype and SubType. Each attribute has a type and a method, respectively. The main difference is SubType inherited SuperType, and inheritance is by creating an instance SuperType, and assign that instance SubType.prototype implementation. Essence prototype object implementation is rewritten, replacing it with a new instance of the type. 

Note : instance.constructor now points to the SuperType, this is because the original SubType.prototype be rewritten in the constructor's sake.

Inadequate : when to implement inheritance through prototype, the prototype will actually become an example of another type. Thus, the original instance properties will naturally become the property of the current prototype. The following code can illustrate the problem:

JS code:

function SuperType(){
    this.colors = ["red", "blue", "green"];
}

function SubType(){
}

SubType.prototype = new SuperType();    //继承了 SuperType

var instance1 = new SubType(); 
instance1.colors.push("black"); 
alert(instance1.colors); //"red,blue,green,black"

var instance2 = new SubType(); 
alert(instance2.colors); //"red,blue,green,black"

复制代码

PS: When creating an instance of a subtype can not pass parameters to the type of super constructor; this deficiency is inherited prototype chain. 


Borrowing Constructor [fake objects or classical inheritance]

The basic idea: within the sub-type constructor calls super type constructor. Functions are just objects to execute code in a specific environment, so by using the apply () and call () method can also be executed in the constructor on the object (in the future) newly created.

JS code:

function SuperType(){
    this.colors = ["red", "blue", "green"];    
}

function SubType(){    
    //继承了 SuperType
    SuperType.call(this);
}

var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);    //"red,blue,green,black"

var instance2 = new SubType();
alert(instance2.colors);    //"red,blue,green"

复制代码

The above code by using the call () method [or apply () method], we actually called a SuperType constructor in the newly created SubType instance environment. This will perform Supertype () function all objects defined in the initialization code in the new SubType object. As a result, each instance has its own copy of SubType attribute of the colors on the city. 

PS: relative prototype chain, borrow constructor has a big advantage, which can pass arguments to a constructor supertype subtype constructor, not illustrated here, just call () method [or apply ( ) method] characteristics.

Inadequate: methods are defined in the constructor, so the function reuse out of the question. Moreover, the methods defined in the super-type prototype, with respect to the sub-type is not visible, the results of all types can only use the constructor mode. 


A combination of inherited [the pseudo-classical inheritance]

The basic idea: the composition and prototype chain technology borrowed to a constructor, both of which play a long one of the inheriting mode. Idea behind using the prototype of the prototype implementation inheritance chain properties and methods, and to achieve an instance attribute inherited by borrowed constructor. 

JS code: 

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age){
    //继承属性 
    SuperType.call(this, name);
    this.age = age;
};

//继承方法
SubType.prototype = new SuperType(); 
SubType.prototype.constructor = SubType; 
SubType.prototype.sayAge = function(){
    alert(this.age);
};

var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors);    //"red,blue,green,black"
instance1.sayName();    //"Nicholas";
instance1.sayAge();    //29

var instance2 = new SubType("Greg", 27); 
alert(instance2.colors);    //"red,blue,green"
instance2.sayName();    //"Greg";
instance2.sayAge();    //27

复制代码

SuperType constructor defines two attributes: name and colors. SuperType prototype defines a method sayName (). SubType constructor passed in the name parameter when calling SuperType constructor, followed by another defines its own properties age. Examples SuperType then SubType is assigned to a prototype, and then defines a method sayAge in the new prototype (). In this way, you can make two different instances SubType both owned their own property - including the colors properties, they can use the same method. 

Combination of inherited and avoids borrowing constructor prototype chain defects, combines their advantages, JavaScript has become the most commonly used mode of inheritance. Further, the instanceof and isPrototypeOf () can also be used to identify objects created based on the combined inheritance. 


Prototypal inheritance 

The basic idea: With a prototype you can create new objects based on existing objects, but also do not have to therefore create a custom type. Refer to the following functions:

JS code:

function object(o){
    function F(){};
    F.prototype = o;
    return new F();
}

复制代码

In the internal object () function, first create a temporary constructor, and then pass the object as the prototype constructor, and returns a new instance of this temporary type. Essentially, object () to perform an incoming object which is shallow copy. 

PS: The prototype formulas in claim inheritance must be as a basis for an object to another object. If there is such an object, then it can be passed to the object () function, then the specific needs of the object to be modified obtained. 

The ECMAScript 5  standardized prototypal inheritance by new Object.create () method.

This method takes two parameters

  1. As the new object prototype object, and (optional)
  2. A custom object additional properties for the new object.
In the case where a parameter is passed, the same behavior as the Object.create () and the object () method. 

JS code:

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends);    //"Shelby,Court,Van,Rob,Barbie"

复制代码

PS: The second parameter Object.defineProperties Object.create () method () method of the second phase format parameter

Same, no explanation here.

Applicable scene: just want to make one object to another object kept under similar circumstances, prototype-style inheritance is fully capable of, but contains a reference to the type of property will always shared values of corresponding value, as using the same prototype mode. 


Parasitic inheritance 

The basic idea: to create a function that is only used to encapsulate the process of succession, the function internally in some way to enhance the object, and finally it is really like to do all the work just returned object. 

JS code:

function createAnother(original){ 
    var clone = object(original);    //通过调用函数创建一个新对象
    clone.sayHi = function(){    //以某种方式来增强这个对象
    alert("hi");
};
    return clone;    //返回这个对象
}

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = createAnother(person);
anotherPerson.sayHi();    //"hi"

复制代码

Based person returns a new object [anotherPerson]; not only new object has all the properties and methods of person, but also has its own sayHi () method. 

Applicable scene: the main consideration objects rather than from the case of defined types and constructors, Parasitic inheritance is a useful model. 


Combined parasitic inheritance 

Here come the combined inheritance explain the problem: no matter under what circumstances, will be called twice over type constructors: one is in the creation of sub-type prototype, and once inside the sub-type constructor. Subtype will eventually contain all the instance properties of super-type object, but we have to rewrite these attributes when invoking the sub-type constructor. 

The following is a combined inheritance:

JS code:

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age){
    SuperType.call(this, name);    // 第二次调用SuperType()
    this.age = age;
}
SubType.prototype = new SuperType();    // 第一次调用SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
    alert(this.age);
};

复制代码

When the first call SuperType constructor, SubType.prototype will get two attributes: name and colors; they are SuperType instance properties, but now located SubType prototypes;

When calling SubType constructor will be the second call SuperType constructor, which in turn creates an instance of a property name and colors on the new object

Thus, these two attributes with the same name on shielding properties of the prototype of the two. 

[Inheritance parasitic modular] The basic idea: to inherit properties by borrowing constructors, methods inherit blend form prototype chain. 

JS code:function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype);    // 创建对象
    prototype.constructor = subType;    // 增强对象
    subType.prototype = prototype;  // 指定对象
}

复制代码

This function accepts two arguments: subtypes and supertypes constructor constructors.

Inside the function, the first step is to create a copy of the super-type prototype.

The second step is to add a copy constructor property is created, thus compensate for the loss of the prototype rewrite the default constructor property. 

The final step, the objects (ie copy) assigned to the newly created sub-type prototype.

In this way, we can use call inheritPrototype () statement function, to replace the statements in the preceding example is a subtype of the prototype of the assignment.

JS code:

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}

inheritPrototype(SubType, SuperType);

SubType.prototype.sayAge = function(){
    alert(this.age);
};

复制代码

PS: parasitic inherited high efficiency is reflected in combined only called once SuperType constructors, and thus avoiding the creation of unnecessary excess in SubType prototype above properties, while the prototype chain can remain unchanged;.

So developers generally believe that the combined parasitic inheritance is the ideal reference types inherit paradigm.


ESMA5 inheritance can be summarized by the following chart:


Well, that's the front Hunzi know six kinds of inheritance ECMA5, where the class ECMA6 omitted inheritance, welcome to leave a message filled with big God.


Finally, I wish you all a happy weekend!



Reproduced in: https: //juejin.im/post/5d006e2de51d45105d63a4eb

Guess you like

Origin blog.csdn.net/weixin_33716557/article/details/93169729