Summary of the six patterns that javascript inherits

  • 2020-05-27 04:16:26
  • OfStack

1. The prototype chain


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

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

The essence of the implementation is to override the prototype object and replace it with an instance of a new type.

2. Borrow the constructor


function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
// inherited 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"

If you just borrow the constructor, you can't avoid the problem with the constructor pattern -- the methods are defined in the constructor, so function reuse is out of the question. Also, the methods defined in the supertype stereotype are not visible to the subtypes, resulting in all types using only the constructor pattern. Given these issues, techniques borrowed from constructors are also rarely used alone.

3. Composite inheritance


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

};
function SubType(name, age){
// Inherit the attributes 
SuperType.call(this, name);
this.age = age;
}
// Inherited methods 
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

In this example, the SuperType constructor defines two properties: name and colors. The prototype of SuperType defines one method, sayName(). The SubType constructor passes in the name parameter when it calls the SuperType constructor, and then defines its own property, age. Then, an instance of SuperType is assigned to the SubType stereotype, and the method sayAge() is defined on the new stereotype. This way, you can have two different instances of SubType have their own properties, including the colors property, and use the same method.

Composite inheritance avoids the pitfalls of prototype chains and borrowed constructors and combines their advantages to become the most common inheritance pattern in JavaScript. Furthermore, instanceof and isPrototypeOf() can also be used to identify objects created based on composite inheritance.

4. Inheritance of original pattern


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

Inside the object() function, a temporary constructor is created, the incoming object is used as the prototype for the constructor, and a new instance of the temporary type is returned. Essentially, object() performs a shallow copy of the object passed in. Consider the following example.


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"

The type of inheritance that crockford advocates requires that you have one object that you can use as a basis for another. If you have such an object, you can pass it to the object() function, and then modify the resulting object according to your specific requirements. In this case, the person object can be used as the basis for another object, so we pass it into the object() function, which then returns a new object. This new object USES person as a stereotype, so its stereotype contains a base type value property and a reference type value property. This means that person.friends is not only owned by person, but also Shared by anotherPerson and yetAnotherPerson. In effect, this is equivalent to creating two more copies of the person object.

ECMAScript 5 standardizes the inheritance of the original model by adding the Object.create () method. This method takes two parameters: an object that is used as a prototype for the new object and (optionally) an object that defines additional properties for the new object. With one parameter passed in, the Object.create () method behaves the same as the object() method.


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"

The second parameter of the Object.create () method is in the same format as the second parameter of the Object.defineProperties () method: each property is defined by its own descriptor. Any property specified in this way overrides the property of the same name on the prototype object. Such as:


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

var anotherPerson = Object.create(person, {
name: {
value: "Greg"
}
});
alert(anotherPerson.name); //"Greg"

Browsers that support the Object.create () method are IE9+, Firefox 4+, Safari 5+, Opera 12+, and Chrome.

In cases where there is no need to create constructors and you only want one object to be similar to another, type inheritance is perfectly acceptable. Don't forget, though, that properties containing reference type values will always share the corresponding values, just as with stereotype schema 1.

5. Parasitic inheritance

Parasitic inheritance (parasitic) is an idea closely related to the original type inheritance, and it was also popularized by crockford. The idea of parasitic inheritance is similar to that of the parasitic constructor and factory pattern, which is to create a function that encapsulates only the inheritance process, internally enhances the object 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); // Create by calling the function 1 A new object 
clone.sayHi = function(){ // Enhance the object in some way 
alert("hi");
};
return clone; // Return this object 
}

In this example, the createAnother() function takes one parameter, which is the object that will be the basis for the new object. Then, pass this object (original) to the object() function and assign the returned result to clone. Add a new method sayHi() to the clone object, and return the clone object. The createAnother() function can be used as follows:


var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

The code in this example returns a new object based on person -- anotherPerson. The new object not only has all the attributes and methods of person, but also has its own sayHi() method.
Parasitic inheritance is also a useful pattern where the primary concern is with objects rather than custom types and constructors. The object() function used to demonstrate the inheritance pattern is not required; Any function that returns a new object applies to this pattern.

Using parasitic inheritance to add functions to an object will reduce efficiency due to function reuse. This 1
Points are similar to the constructor pattern.

6. Parasitic combinatorial inheritance

As mentioned earlier, composite inheritance is the most commonly used inheritance pattern for JavaScript; But it has its drawbacks. The biggest problem with combinatorial inheritance is that the supertype constructor is called twice in any case: once when creating the subtype stereotype, and once inside the subtype constructor. Yes, the subtypes end up containing all the instance properties of the supertyped object, but we have to override these properties when we call the subtype constructor. Let's take another look at 1 and look at the following example of combinatorial inheritance.


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); // The first 2 Time to call SuperType()
this.age = age;
}
SubType.prototype = new SuperType(); // The first 1 Time to call SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
};

The line in bold is the code that calls the SuperType constructor. On the first call to the SuperType constructor, SubType.prototype gets two properties: name and colors; They are both instance properties of SuperType, except that they are now in the prototype of SubType. When the SubType constructor is called, the SuperType constructor is called once more, which creates the instance properties name and colors on the new object. Thus, these two properties mask the two properties of the same name in the stereotype. Figure 6-6 shows the above process.
As shown in figure 6-6, there are two groups of name and colors properties: 1 group on the instance and 1 group in the SubType stereotype. This is the result of calling the SuperType constructor twice. The good news is that we have found a solution to this problem -- parasitic combinatorial inheritance.

The so-called parasitic combinatorial inheritance means that properties are inherited by borrowing constructors and methods are inherited by mixing them into a prototype chain. The basic idea behind this is that instead of calling the supertype constructor to specify the subtype stereotype, all we need is a copy of the supertype stereotype. Essentially, you use parasitic inheritance to inherit the supertype stereotype, and then assign the result to the subtype stereotype. The basic pattern of parasitic combinatorial inheritance is shown below.


function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
// inherited 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"

0

The inheritPrototype() function in this example implements the simplest form of parasitic combinatorial inheritance. This function takes two arguments: the subtype constructor and the supertype constructor. Inside the function, step 1 is to create a copy of the supertype prototype. The second step is to add the constructor property to the replica created to compensate for the loss of the default constructor property due to the overwriting of the stereotype. The last step is to assign the newly created object (that is, the copy) to the prototype of the subtype. This allows us to replace the subtype stereotype assignment in the previous example with the statement that calls the inherit-Prototype () function, for example


function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
// inherited 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"

1

This example is efficient in that it calls the SuperType constructor only once, and thus avoids creating unnecessary, redundant properties on SubType.prototype. At the same time, the prototype chain remains the same; Therefore, instanceof and isPrototypeOf() can also be used normally. It is generally accepted by developers that parasitic combinatorial inheritance is the ideal inheritance paradigm for reference types.

YUI's YAHOO.lang.extend () method USES parasitic combinatorial inheritance, making this pattern available for the first time in a very widely used JavaScript library. For more information about YUI, please visit http:// developer.yahoo.com /yui/.

That's all for this article, and I hope it will be helpful for you to learn javascript inheritance.


Related articles: