There are 6 ways to implement inheritance in native JS (ES5) :

  • 1. Inheritance through the prototype chain
  • 2, borrow constructor inheritance
  • 3. Combination inheritance
  • 4. Inheritance of the original type
  • 5. Parasitic inheritance
  • Parasitic combination inheritance

What the new operator does:

  • Create a new object in memory
  • 2. The [[Prototype]] pointer inside the new object is assigned to the constructor’s Prototype property
  • 3. This inside the constructor is assigned to the new object (i.e. this refers to the new object).
  • 4, execute the code inside the constructor (add properties to the new object)
  • If the constructor returns a non-empty object, return that object. Otherwise, the newly created object is returned

1. Inheritance through the prototype chain:

/** * 1. Inheriting through the stereotype chain * has the following disadvantages: * reference values contained in a stereotype are shared among all instances, and if you modify one instance, the other instance will be modified * that is, by defining attributes in the constructor ** when subclasses are instantiated, you cannot pass arguments to the constructor of the parent class */

/ / parent class
function SuperType() {
    this.colors = ['red'.'blue'.'green']}/ / subclass
function SubType() { }
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"
Copy the code

2, borrow constructor inheritance

/** * 2, ** * * to ensure that SuperType constructors do not overwrite properties defined by SubType, subclasses are not allowed to access methods defined on a superclass prototype. * You can add additional properties to a subclass instance after calling the superclass constructor */

/ / parent class
function SuperType(name) {
    this.name = name
}
/ / subclass
function SubType(name1) {
    SuperType.call(this, name1)
    this.age = 28
}
let instance1 = new SubType('Test name')
console.log(instance1.name) // Test name
console.log(instance1.age) / / 28
Copy the code

3. Combinatorial inheritance

/** * 3, combinative inheritance has the following disadvantages: (1) Combinative inheritance has the efficiency problem, the superclass constructor is called twice, * first in the creation of the subclass prototype, second in the subclass constructor * eventually the subclass prototype contains all the instance properties of the superclass */

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); // Call SuperType() the second time
    this.age = age;
}
SubType.prototype = new SuperType(); // First call to SuperType()
SubType.prototype.constructor = SubType;
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
Copy the code

4. Inheritance of the original type

The disadvantages of prototype inheritance are as follows: * Reference values contained in 1 properties are shared between objects * Note: ECMAScript 5 normalizes the concept of prototype inheritance by adding the object.create () method. The second argument to object.create () is the same as the second argument to object.defineProperties () */. The second argument to object.create () is the same as the second argument to object.defineProperties () */
function object(o) {
	function F() { }
	F.prototype = o
	return new F()
}

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"
Copy the code

5. Parasitic inheritance

Adding a function to an object makes the function difficult to reuse, similar to the constructor pattern. * /

function createAnother(original) {
    let clone = object(original); // Create a new object by calling a function
    clone.sayHi = function () { // Enhance the object in some way
            console.log("hi");
    };
    return clone; // Return this object
}
let person = {
    name: "Nicholas".friends: ["Shelby"."Court"."Van"]};let anotherPerson = createAnother(person);
anotherPerson.sayHi(); // "hi"
Copy the code

Parasitic combination inheritance

/** * 6

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);
};
Copy the code
Summary: The common inheritance methods use composite inheritance, parasitic combination inheritance, specific scenarios specific use