JavaScript Advanced Programming Reading Sharing Chapter 8 - 8.3 Inheritance

JavaScript Advanced Programming (4th Edition) Reading Sharing Note Recording

Applicable to comrades who are just getting started

 prototype chain

ECMA-262 defines the prototype chain as the main inheritance method of ECMAScript .

The meaning of the prototype chain: each constructor has a prototype object (prototype), the prototype object has a property ( constructor ) pointing back to the constructor, and the instance has an internal pointer (__proto__) pointing to the prototype object . What if the prototype is an instance of another type (we make the prototype object equal to an instance of another type)? That means that the prototype itself has an internal pointer to another prototype, which in turn has a pointer to another constructor. This constructs a prototype chain between the instance and the prototype. This is the basic idea of ​​the prototype chain.

Prototype objects, constructors, and instance explanations are mentioned in the previous chapter

example:

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; 
}; 
let instance = new SubType();

Such a layer-by-layer progression constitutes a chain of instances and prototypes, forming a prototype chain

 

default prototype

        In fact, there is one more link in the prototype chain. By default, all reference types inherit from Object , which is also achieved through the prototype chain. The default prototype of any function is an instance of Object, which means that this instance has an internal pointer to
Object.prototype
Added Object's prototype chain diagram:

 Prototype and Inheritance

The prototype-to-instance relationship can be determined in two ways:
        The first way is to use the instanceof operator. If the corresponding constructor appears in the prototype chain of an instance, instanceof returns true .
Or take the above code as an example:
        
console.log(instance instanceof Object); // true 
console.log(instance instanceof SuperType); // true 
console.log(instance instanceof SubType); // true
The second way to determine this relationship is to use the isPrototypeOf() method, which returns true as long as the prototype is contained in the prototype chain :
console.log(Object.prototype.isPrototypeOf(instance)); // true 
console.log(SuperType.prototype.isPrototypeOf(instance)); // true 
console.log(SubType.prototype.isPrototypeOf(instance)); // true

Prototype chain problem

        The main problem occurs when the prototype contains reference values . As mentioned earlier when talking about the prototype, the reference value contained in the prototype will be shared among all instances, which is why attributes are often defined in the constructor and not on the prototype.
example:
function SuperType() { 
 this.colors = ["red", "blue", "green"]; 
} 
function SubType() {} 
// 继承 SuperType 
SubType.prototype = new SuperType(); 
let instance1 = new SubType(); 
instance1.colors.push("black"); 
console.log(instance1.colors); // "red,blue,green,black" 
let instance2 = new SubType(); 
console.log(instance2.colors); // "red,blue,green,black"

Stealing constructor

In order to solve the inheritance problem caused by the prototype containing the reference value

The basic idea is simple: call the parent class constructor in the subclass constructor. Constructors can be executed in the context of the newly created object using the apply() and call() methods.

example:

function SuperType() { 
 this.colors = ["red", "blue", "green"]; 
} 
function SubType() { 
 // 继承 SuperType 
 SuperType.call(this); 
} 
let instance1 = new SubType(); 
instance1.colors.push("black"); 
console.log(instance1.colors); // "red,blue,green,black" 
let instance2 = new SubType(); 
console.log(instance2.colors); // "red,blue,green"

Composition inheritance

Combined inheritance (sometimes called pseudo-classical inheritance) combines the prototype chain and the stolen constructor, and combines the advantages of both
The basic idea: use the prototype chain to inherit the properties and methods on the prototype , and inherit the instance properties by stealing the constructor .

Combination inheritance makes up for the shortcomings of prototype chain and stolen constructor, and is the most used inheritance mode in JavaScript
example:
function SuperType(name){ 
    
//实例属性
 this.name = name; 
 this.colors = ["red", "blue", "green"]; 
} 
//原型链属性,方法
SuperType.prototype.sayName = function() { 
 console.log(this.name); 
}; 
function SubType(name, age){ 
 // 继承属性
 SuperType.call(this, name); 
 this.age = age; 
} 
// 继承方法
SubType.prototype = new SuperType(); 
SubType.prototype.sayAge = function() { 
 console.log(this.age); 
}; 
let instance1 = new SubType("Nicholas", 29); 
instance1.colors.push("black"); 
console.log(instance1.colors); // "red,blue,green,black" 
instance1.sayName(); // "Nicholas"; 
instance1.sayAge(); // 29 


let instance2 = new SubType("Greg", 27); 
console.log(instance2.colors); // "red,blue,green" 
instance2.sayName(); // "Greg"; 
instance2.sayAge(); // 27

prototypal inheritance

Example of prototypal inheritance:

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

let anotherPerson = object(person); 
anotherPerson.name = "Greg"; 
anotherPerson.friends.push("Rob");
 
let yetAnotherPerson = object(person); 
yetAnotherPerson.name = "Linda"; 
yetAnotherPerson.friends.push("Barbie"); 
console.log(person.friends); // "Shelby,Court,Van,Rob,Barbie"

        The object() method used here creates a temporary constructor, assigns the incoming object to the prototype of the constructor, and then returns an instance of the temporary type.

ECMAScript 5 normalized the concept of prototypal inheritance         by adding the Object.create() method. This method takes two parameters: the object that is the prototype of the new object, and the object (the second is optional) that defines additional properties for the new object. Object.create() has the same effect as the object() method here when there is only one parameter .
        Prototype inheritance is very suitable for situations where you don't need to create separate constructors, but you still need to share information between objects. But keep in mind that reference values ​​contained in properties are always shared between related objects, just like using the prototype pattern.

parasitic compositional inheritance

Combination inheritance actually has efficiency problems. The main efficiency problem is that the parent class constructor will always be called twice: once in the
Called when the subclass prototype is created, and the other time is called in the subclass constructor, so parasitic combination inheritance was born
example:
function inheritPrototype(subType, superType) { 
 let prototype = object(superType.prototype); // 创建对象
 prototype.constructor = subType; // 增强对象 
 subType.prototype = prototype; // 赋值对象
}

function SuperType(name) { 
 this.name = name; 
 this.colors = ["red", "blue", "green"]; 
} 
SuperType.prototype.sayName = function() { 
 console.log(this.name); 
}; 
function SubType(name, age) { 
 SuperType.call(this, name); 
  this.age = age; 
} 

inheritPrototype(SubType, SuperType); 

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

Guess you like

Origin blog.csdn.net/weixin_42307283/article/details/129357003