One, foreword

Inheritance means that a subclass can access the attributes and methods of its parent class, so implementing inheritance means that a subclass can access the methods of its parent class

Two, the implementation of inheritance methods

1. Embezzle constructors

The principle behind embeded constructor inheritance is that all the code of the parent function is executed on top of the child function, so each instance constructed through the child function has its own attributes and methods inherited from the parent function, and no reference values are shared between instances

  • The subclass constructor can pass arguments to the parent constructor,
function Father(name) {
  this.arr = [1.2.3]
  this.name = name
}

function Son(name) {
  Father.call(this, name)
  this.age = 10 
  To ensure that the attributes of the parent function do not override the attributes of the child function, the attributes defined by the child function are executed after the parent function is called
}

let son = new Son()

console.log(son.arr);
Copy the code

disadvantages

  • A subclass cannot access a method defined on its parent class’s prototype, because the subclass’s prototype object is not overridden as an instance of the parent class. The subclass just executes the parent class’s content. What else does it matter

2. Prototype chain inheritance

The basic principle of prototype chain inheritance is to rewrite the prototype object of a subclass as an instance of the parent class

function Father() {
  this.arr = [1.2.3]}function Son() {}// Overrides the prototype object as an instance of the parent class, son.prototype. __proto__ == Father. Prototype
Son.prototype = new Father()

let son1 = new Son()

son1.arr.push(4) 
let son2 = new Son()

console.log(son1.arr);  // [1, 2, 3, 4]
console.log(son2.arr);  // [1, 2, 3, 4]
Copy the code

disadvantages

  • Instance objects share reference values in the prototype object, and if one instance modifies the prototype object, the other instances inherit the changes
  • Subclasses cannot pass arguments to parent functions when instantiated
  • As shown in figure

3. Combinatorial inheritance

Combinatorial inheritance combines prototype chain and embeded constructor. The basic implementation is to inherit attributes and methods on parent class prototype through prototype chain, and inherit instance attributes through embeded constructor

  • Each instance of a subclass extends the subclass’s constructor by stealing the constructor, so that when all subclasses construct objects in new, all attributes are unique to the instance and are not shared by the instance, solving the case where instances share reference values in the prototype chain
  • By rewriting the prototype of a subclass as a parent class instance object, we inherit the methods of the parent class prototype and make up for the deficiency of the stolen constructor
function Father(name) {
  this.name = name 
  this.array = [1.2.3]
}

Father.prototype.sayName = function() {
  console.log(this.name)
}

function Son(name, age) {
  Father.call(this, name)
  this.age = age
}

// Reassign the prototype of the subclass to the instance of the parent class to implement inheritance
Son.prototype = new Father()

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

let instance1 = new Son('zhangsan'.30)
// Push is a push element on its own array property, independent of its prototype object
instance1.array.push(4)
console.log(instance1.array)  // [1, 2, 3, 4]
instance1.sayName()
instance1.sayAge()

let instance2 = new Son('lisi'.59)
// Instance 1 array change does not affect instance 2,
console.log(instance2.array); / / [1, 2, 3]
instance2.sayName()
instance2.sayAge()
Copy the code

4. Original type inheritance

Primitive inheritance is used when you have an object and want to create a new object based on it that has access to the properties and methods of the original object

function createObj(obj) {
  function F() {}
  F.prototype = obj
  return new F()
}

let obj = {
  name: 'zhangsan'.arr: [1.2.3]}let newObj = createObj(obj)

console.log(newObj.name); // zhangsan
Copy the code

disadvantages

  • The newly created objects share managed objects. If one object modifies the reference value of the associated object, the other objects will change, as shown in the figure

  • ES5’s create method does the same thing

Parasitic inheritance

Parasitic inheritance is to add methods to a new object based on the original type inheritance, which is also suitable for known objects without paying attention to constructors.

function createObj(obj) {
  let clone = Object.create(obj)
  // Enhance this object
  clone.newFunc = function() {
    console.log(this.name);
  }
  return clone
}


let obj = {
  name: 'zhagnsa'
}

let newObj = createObj(obj)
newObj.newFunc()
Copy the code

disadvantages

  • Adding new methods to objects is difficult to reuse,

Parasitic combinatorial inheritance

Parasitic combinatorial inheritance solves the problem of combinatorial inheritance calling the parent constructor twice, changing the stereotype approach of inheriting a parent class by overriding the subclass stereotype as an instance of the parent class. Use parasitic inheritance to implement a stereotype method that inherits from the parent class and returns it to the subclass stereotype.

function createObj(obj) {
  function F() {}
  F.prototype = obj
  return new F()
}

function inheritPrototype(son, father) {
  // Create a prototype pointer to the object of the superclass prototype
  const prototype = createObj(father.prototype)
  // Fix the constructor property missing due to rewriting the prototype
  prototype.constructor = son
  son.prototype = prototype 
}

function Father(name) {
  this.name = name
  this.array = [1.2.3]
}

Father.prototype.sayName = function() {
  console.log(this.name);
}

function Son(name, age) {
  Father.call(this, name)
  this.age = age
}

inheritPrototype(Son, Father)

Son.prototype.sayAge = function() {
  console.log(this.age);
}
Copy the code

As is shown in

6. ES6 class inheritance

  class Person {
    constructor(name, age) {
      this.name = name
      this.age = age
    }
    sex = 'male' 
    // Defined on the prototype object
    getName() {
      return this.name
    }
    // Defined on the class name
    static getAge() {
      console.log(123); }}let zhangsan = new Person('zhangsan'.10)

  class Student extends Person{
    constructor(name, age, studentNum) {
      // super calls the constructor of the parent class. Super can only be used in the constructor and static methods of subclasses
      // If a subclass does not define a constructor method, the subclass automatically inherits properties and methods from its parent class
      // If you define a constructor, you must say super inherits the superclass method
      super(name, age, studentNum)
      this.studentNum = studentNum
    }
  }


let stu1 = new Student('name'.'age'.' ')

console.log(stu1
);
console.log(stu1.getName());
Copy the code

References: Javascript Advanced Programming