Preface:

This article summarizes the common implementation of JS inheritance, examples and some annotations are their own thinking, welcome to exchange, the structure of the main reference to this article 1.

mapping

ES5 and its predecessors

1. Prototype chain inheritance

Let’s take a look at the prototype chain inheritance method, the code is as follows:

 function Person() {
  this.nation = ["china"];
} // Internal attributes

Person.prototype.say = function () {
  let res = this.nation;
  res = `I have been ${res}`;
  return res;
}; // Attribute methods on prototype objects

function Chinese() {}
Chinese.prototype = new Person(); // This is inherited from prototype

p1 = new Chinese();
p1.nation.push("japan");
p2 = new Chinese();
p2.nation = "korea"; // This is equivalent to applying a new space and assigning it to p2.nation
p3 = new Chinese();
p3.nation.push("america");
console.log("p1", p1);
console.log("p2", p2); 
console.log("p3", p3); // note that p3 and P1 share the same nation

// So there are two problems with this approach
// Problem 1: The reference type attribute contained in the stereotype will be shared by all instances;
// Problem 2: A subclass cannot take arguments to its parent constructor when instantiated;
Copy the code

Let’s take a look at the result, as shown belowAs can be seen from the picture above,p1In the callPersonPrototype object (prototype)sayMethod for a reference type on the stereotypenationIt’s shared, sop1I’ve been to America. whilep2theBecause assignment is in the lexical phase, an append is applied to P2nationAttribute, when JS is running, it will not go to the prototype chain when it has the required attribute, so there is no common prototype chain herenation.

2. Borrow constructor inheritance

function Person(name) {
  this.name = name;
  this.nation = ["china"];
  this.say = function () {
    let res = this.nation;
    res = `I have been ${res}`;
    return res;
  };
}

function Chinese(name) {
  Person.call(this, name); // bind this
}

Chinese.prototype = new Person(); // here is the inheritance

p1 = new Chinese("Li Hua");
p1.nation.push("japan");
p2 = new Chinese("Han Mei Mei");
p2.nation = "korea";
p3 = new Chinese("Lao Wang");
p3.nation.push("america");
console.log("p1", p1);
console.log("p2", p2);
console.log("p3", p3);
// While this approach solves the problem of non-passable parameters in the prototype mode, and sharing with reference types,
// But it also introduces a new problem, that is, object methods are recreated every time an instance is created
Copy the code

The running results are as follows:As we can see, this approach addresses two of the shortcomings of the stereotype approach: it can pass parameters, and it is not common to reference type attributes on the stereotype. However, it is also clear that each instance object creates the say method repeatedly, which is a new shortcoming.

3. Combinatorial inheritance

The code is as follows:

function Person(name) {
  this.name = name;
  this.nation = ["china"];
}
// The public method is still a prototype object
Person.prototype.say = function () { 
  let res = this.nation;
  res = `I have been ${res}`;
  return res;
};

function Chinese(name, age) {
  Person.call(this, name); // Private attributes make use of constructors, specifying constructor as itself below
  this.age = age;
}

Chinese.prototype = new Person(); // Inherit the name nation and say methods
Chinese.prototype.constructor = Chinese; // Use The Chinese constructor

p1 = new Chinese("Li Hua".16);
p1.nation.push("japan");
p2 = new Chinese("Han Mei Mei".16);
p2.nation = "korea";
p3 = new Chinese("Lao Wang".35);
p3.nation.push("america");
console.log("p1", p1);
console.log("p2", p2);
console.log("p3", p3);
Copy the code

The running results are as follows:As shown above: composite inheritance is combinedPrototype chain modeandBorrow the constructor approachAnd bring together the advantages of both. The basic idea is to use stereotype chains to inherit properties and methods on stereotypes, and to inherit instance properties by stealing constructors. This allows methods to be defined on prototypes for reuse and allows each instance to have its own attributes.

4. Parasitic combinatorial inheritance

// Composite inheritance is relatively complete, but there are still problems with it. The problem is that the parent constructor is called twice
// First in person.call (this,name) and second in new Person()
// The new operator is no longer used in line 20
function Person(name) {
  this.name = name;
  this.nation = ["china"];
}

Person.prototype.say = function () {
  let res = this.nation;
  res = `I have been ${res}`;
  return res;
};

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

Chinese.prototype = Object.create(Person.prototype); // Inherit the name nation and say methods, but no longer call them with new.
Chinese.prototype.constructor = Chinese; // Use The Chinese constructor

p1 = new Chinese("Li Hua".16);
p1.nation.push("japan");
p2 = new Chinese("Han Mei Mei".16);
p2.nation = "korea";
p3 = new Chinese("Lao Wang".35);
p3.nation.push("america");
console.log("p1", p1);
console.log("p2", p2);
console.log("p3", p3);

Copy the code

The running results are as follows:

Ii. Inheritance mode of ES6

The class way

class Person {
  constructor(name) {
    this.name = name;
    this.nation = ["china"];
  }
  say() {
    let res = this.nation;
    res = `I have been ${res}`;
    returnres; }}class Chinese extends Person {
  constructor(name, age) {
    super(name);
    this.age = age;
  }
}

p1 = new Chinese("Li Hua".16);
p1.nation.push("japan");
p2 = new Chinese("Han Mei Mei".16);
p2.nation = "korea";
p3 = new Chinese("Lao Wang".35);
p3.nation.push("america");
console.log("p1", p1);
console.log("p2", p2);
console.log("p3", p3);
Copy the code

The running results are as follows:In class, we find that the class implementation behaves almost the same as the ES5 parasitic composite implementation, but is much cleaner. Through step by step implementation and comparison, we better understand the prototype chain and other related basic knowledge. If this article has been helpful to you, please feel free to share with me in the comments section. Thank you very much!


  1. Mp.weixin.qq.com/s/mG3MTIQFc…↩