1. The prototype chain

The concept of stereotype chains is described in ECMAScript as the primary method of implementing inheritance. The basic idea is to use stereotypes to make one reference type inherit the properties and methods of another.

A prototype chain can be constructed by:

    function SuperType(){
        this.property = true;
    }
    
    SuperType.prototype.getSuperValue = function(){
        return this.property;
    };
    
    function SubType(){
        this.subproperty = false;
    }
    
    //inherit from SuperType
    SubType.prototype = new SuperType();
    
    SubType.prototype.getSubValue = function (){
        return this.subproperty;
    };
    
    var instance = new SubType();
    alert(instance.getSuperValue());   //true
Copy the code

There are two ways to determine the relationship between stereotypes and instances: instanceof

alert(instance instanceof Object); //true alert(instance instanceof SuperType); //true alert(instance instanceof SubType); / / true or isProtoyepeOf alert (Object. The prototype. IsPrototypeOf (instance)); //true alert(SuperType.prototype.isPrototypeOf(instance)); //true alert(SubType.prototype.isPrototypeOf(instance)); // True prototype chain problem:

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

    function SubType(){            
    }
    
    //inherit from SuperType
    SubType.prototype = new 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"
Copy the code

As mentioned earlier, reference types are shared, okay?

The second problem with stereotype chains is that when creating instances of subtypes, arguments cannot be passed in the constructor of a supertype. In fact, there is no way to pass arguments to a supertype constructor without affecting all object instances. Because of this, and because of the problems with stereotypes containing reference type values just discussed earlier, prototype chains alone are rarely used in practice.

2. Borrow constructors

The technique of constructor stealing is sometimes called constructor object stealing or classical inheritance. The basic idea of this technique is to call the supertype constructor inside the subtype constructor. Such as:

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

    function SubType(){  
        //inherit from 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"
Copy the code

The supertype.call (this) line of code borrows the constructor for the SuperType. By using the call() method, or perhaps apply() method, we are actually calling the SuperType constructor in the context of the newly created SubType instance (which we will). This will execute all the object initialization code defined in the SuperType() function on the new SubType object. As a result, each instance of SubType has its own copy of the Colors attribute.

Borrowing constructors have a big advantage over prototype chains, passing arguments to supertype constructors in subtype constructors.

function SuperType(name){ this.name = name; }

function SubType(){ //inherit from SuperType passing in an argument SuperType.call(this, "Nicholas"); //instance property this.age = 29; } var instance = new SubType(); alert(instance.name); //"Nicholas"; alert(instance.age); / / 29Copy the code

The problem with constructor stealing is that it is impossible to avoid the problem of the constructor pattern: methods are defined within constructors, so function reuse is out of the question. Furthermore, methods defined in the stereotype of a supertype are also invisible to subtypes, resulting in only the constructor schema being used for all types.

3. Combinatorial inheritance

Combination inheritance, sometimes called pseudo-classical inheritance, refers to an inheritance pattern that combines a chain of archetypes and techniques borrowed from constructors to exploit the best of both. The idea behind this is to use stereotype chains to inherit stereotype attributes and methods, while borrowing constructors to inherit instance attributes.

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.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(); / / 27Copy the code

Stereotypes allow you to create new objects based on existing objects without having to create custom types. To do this, he gave the following function

function object(o){ function F(){}

F.prototype=o;

return new F();

}

Inside the object function, a temporary constructor is created, the passed object is used as a prototype for the constructor, and a new instance of the temporary type is reversed. In essence, object() makes a shallow copy of the object passed into it.

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    
    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
    
    var anotherPerson = object(person);
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
    
    var yetAnotherPerson = object(person);
    yetAnotherPerson.name = "Linda";
    yetAnotherPerson.friends.push("Barbie");
    
    alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
Copy the code

This primitive inheritance requires that you have an object that can be used as a base for another object, and if you have one, you can pass it to the object() function and then modify the resulting object as needed. ECMAScript5 takes old-style inheritance with the new object.create () method specification, which takes two parameters: an Object to be used as a prototype for the new Object and (optionally) an Object that defines additional properties for the new Object. The object.create () method behaves the same as the Object () method when passed a parameter. 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"
Copy the code

Parasitic inheritance was a form of thinking closely associated with parasitic inheritance. The idea of parasitic inheritance is similar to that of the parasitic constructor and factory pattern, which is to create a function that just encapsulates the inheritance process, enhances the object internally in some way, and finally returns the object as if it really did all the work. The following code demonstrates the parasitic inheritance pattern.

function createAnother(original){ var clone=object(original);

clone.sayHi=function(){ alert(“hi”);

}

return clone;

} In this example, createAnother() takes an argument, which is the object that will be the base of the new object. This object (Original) is then passed to the object () function, which assigns the result to Clone. Add a new method sayHi () to the Clone object and return it. You can use createAnother () like this:

var person={ name:”asd”,

friends:[“q”,”w”,”e”]

};

var anotherPerson=createAnother(person);

anotherPerson.sayHi();

Parasitic combinatorial inheritance refers to inheriting properties by borrowing constructors and inheriting methods through a hybrid form of stereotype chains. The basic idea behind this is that instead of calling the constructor of the supertype to specify the stereotype of the subtype, all you need is a copy of the stereotype of the supertype. In essence, we use parasitic inheritance to inherit the stereotype of the supertype, and then assign the result to the stereotype of the subtype. The basic mode of parasitic combination is as follows:

function inheritPrototype(subType,superType){ var prototype=object(superType.prototype); // Create an object

prototype.constructor=subType; // Enhance objects

subType.prototype=prototype; // Specify the object

}

function object(o){ function F(){} F.prototype = o; return new F(); } function inheritPrototype(subType, superType){ var prototype = object(superType.prototype); //create object prototype.constructor = subType; //augment object subType.prototype = prototype; //assign object } 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); }; 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(); / / 27Copy the code

The efficiency of this example is that it only calls the SuperType constructor once, and thus avoids creating unnecessary, redundant attributes on subtype. protorype. At the same time, the prototype chain can remain unchanged. YUI’s Yahoo.lang.extend () method uses parasitic composite inheritance.