Three Inheritance Modes in js and Their Advantages and Disadvantages

  • 2021-07-09 07:14:15
  • OfStack

The first way, prototype:


// Parent class  
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

// Subclass  
function man(){ 
  this.feature = ['beard','strong']; 
} 

man.prototype = new person(); 
var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow 

This is the simplest way to get the prototype attribute value of the subclass assigned to one instance of the inherited class, and then you can use the methods of the inherited class directly.

What does the prototype attribute mean? prototype is a prototype, and every object (defined by function) has a default prototype attribute, which is an object type.

And this default attribute is used to realize the upward climbing of the chain. This means that if the attribute of an object does not exist, the prototype attribute will be found by the object to which it belongs. What if prototype can't find it?

js will automatically find the object to which the prototype attribute of prototype belongs, so that it can climb up the index through prototype1 until the attribute is found or prototype is finally empty ("undefined");

For example, in the above example, one. view () method, js will first look for view () method in one instance, because there is no man. prototype attribute, and the value of prototype is one instance of person.

The instance has the view () method, so the call is successful.

Second, the way of apply:


// Parent class  
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

// Subclass  
function man(){ 
  // person.apply(this,new Array()); 
  person.apply(this,[]); 
  this.feature = ['beard','strong']; 
} 

var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow 

Note: If the apply parameter is null, that is, no parameter is passed, it is passed through new Array (), [], and null is invalid.

The third way, call+prototype:


// Parent class  
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

// Subclass  
function man(){ 
  // person.apply(this,new Array()); 
  person.call(this,[]); 
  this.feature = ['beard','strong']; 
} 

man.prototype = new person(); 
var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow 

The implementation mechanism of call mode needs one more man. prototype = new person (); Why?
That's because the call method only implements method substitution and does not copy object properties.
This is how google Map API is inherited.

The implementation of three inheritance methods is summarized above. But each method has its advantages and disadvantages.

If the parent class is like this:


// Parent class  
function person(hair,eye,skin){ 
  this.hair = hair; 
  this.eye = eye; 
  this.skin = skin; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

How should the subclass be designed so that the subclass man passes parameters to the parent class person while creating objects, and the inheritance mode of prototype is not applicable.
apply or call must be adopted:


//apply Mode  
// Subclass  
function man(hair,eye,skin){ 
  person.apply(this,[hair,eye,skin]); 
  this.feature = ['beard','strong']; 
} 
//call Mode  
// Subclass  
function man(hair,eye,skin){ 
  person.call(this,hair,eye,skin); 
  this.feature = ['beard','strong']; 
} 

However, there are still disadvantages in apply method. Why? In js, we have a very important operator "instanceof", which is used to compare whether a certain alignment is of a certain type.

For this example, the one instance should be person as well as man type, but after apply mode inheritance, one does not belong to person type, that is, the value of false (one instanceof person) is false.

After all this, the best way to inherit is call + prototype, and then you can try whether the value (one instanceof BaseClass) is true.

The third inheritance method also has defects: when subclass new objects pass the parameters required by the parent class once, and reproduce the attributes and methods in the parent class. The following inheritance method is perfect:


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

Person.prototype.getName = function() { 
  return this.name; 
} 

function Chinese(name, nation) { 
  Person.call(this, name); 
  this.nation = nation; 
} 

// Inheritance method  
function inherit(subClass, superClass) { 
  function F() {} 
  F.prototype = superClass.prototype; 
  subClass.prototype = new F(); 
  subClass.prototype.constructor = subClass.constructor; 
} 

inherit(Chinese, Person); 

Chinese.prototype.getNation = function() { 
  return this.nation; 
}; 

var p = new Person('shijun'); 
var c = new Chinese("liyatang", "China"); 

console.log(p); // Person {name: "shijun", getName: function} 
console.log(c); // Chinese {name: "liyatang", nation: "China", constructor: function, getNation: function, getName: function} 


console.log(p.constructor); // function Person(name){} 
console.log(c.constructor); // function Chinese(){} 

console.log(c instanceof Chinese); // true 
console.log(c instanceof Person); // true 

Related articles: