js inheritance method

Prototype chain inheritance

The most common inheritance methods involve constructors, prototypes, and instances

  1. Each constructor has a prototype object
  2. The prototype object also contains a pointer to the constructor
  3. The instance contains a pointer to the prototype object
    There are problems with this inheritance

    function Parent(){
     this.name="parent"
     this.own = [1,2,3]
    }
    
    function Child(){
     this.type ="child"
    }
    Child.prototype = new Parent()
    console.log(new Child())  // Parent { type: 'child' }
    
    let c1 = new Child();
    let c2 = new Child();
    c1.own.push(4)
    console.log(c1.own,c2.own) // [ 1, 2, 3, 4 ] [ 1, 2, 3, 4 ]

    Because the two instances use the same prototype object and share memory space, when one changes, the other also changes

Constructor inheritance

call implementation

function Parent(){
    this.name="parent"
    this.own = [1,2,3]
}
Parent.prototype.getName = function () {
    return this.name;
  }

function Child(){
    Parent.call(this)
    this.type ="child"
}
const child = new Child()
console.log(child)  // Child { name: 'parent', own: [ 1, 2, 3 ], type: 'child' }
console.log(child.getName())   // child.getName is not a function

This method solves the disadvantages of prototype shared memory, which also brings new problems. Only instance properties and methods of the parent class can be inherited, and prototype properties or methods cannot be inherited.

Combinatorial inheritance

This method combines the advantages and disadvantages of the first two inheritance methods and combines inheritance

function Parent(){
    this.name="parent"
    this.own = [1,2,3]
}
Parent.prototype.getName = function () {
    return this.name;
  }

function Child(){
    // Second call
    Parent.call(this)
    this.type ="child"
}
// Calling Parent3() for the first time
Child.prototype = new Parent()
// Manually hang up the constructor and point to its own constructor
Child.prototype.constructor = Child;

let c1 = new Child()
let c2 = new Child()
c1.own.push(4)
console.log(c1.own,c2.own)  // [ 1, 2, 3, 4 ] [ 1, 2, 3 ]
console.log(c1.getName())  // parent
console.log(c2.getName())  // parent

The Parent is executed twice. The first time is to change the Child's prototype, and the second time is to call the Parent through the call method. If the Parent is constructed once more, it will incur an additional performance overhead

Prototype inheritance

Use the object in ES5 Create method, which receives two parameters: one is the object used as the prototype of the new object, and the other is the object that defines additional properties for the new object (optional parameters)

let parent = {
    name:"parent",
    friend:['1',',2','3'],
    getName:function(){
        return this.name
    }
}

let p1 = Object.create(parent)
p1.name ="jake"
p1.friend.push("a")

let p2 = Object.create(parent)
p1.friend.push("b")

console.log(p1.name)  // jake
console.log(p1.name === p1.getName())   // true
console.log(p2.name) // parent
console.log(p1.friend) // [ '1', ',2', '3', 'a', 'b' ]
console.log(p2.friend) // [ '1', ',2', '3', 'a', 'b' ]

The disadvantages of this inheritance method are obvious. The reference type properties of multiple instances point to the same memory, which may be tampered with

Parasitic inheritance

Prototype inheritance can obtain a shallow copy of the target object, and then enhance the ability of this shallow copy and add some methods. This inheritance method is called parasitic inheritance
The advantages and disadvantages are the same as prototype inheritance, but for the inheritance of ordinary objects, parasitic inheritance adds more methods on the basis of parent class than prototype inheritance

let parent = {
    name:"parent",
    friend:['1',',2','3'],
    getName:function(){
        return this.name
    }
}

function clone(src) {
    let clone = Object.create(src);
    clone.getFriends = function() {
      return this.friend;
    };
    return clone;
  }

let p1 =clone(parent)
console.log(p1.getName())  // parent
console.log(p1.getFriends())   // [ '1', ',2', '3' ]

The method of getFriends is added, so that p1, an ordinary object, adds another method in the inheritance process. It still calls the constructor of the parent class twice, resulting in waste

Parasitic combinatorial inheritance

Solve the shortcomings of the previous inheritance methods, better achieve the desired results of inheritance, reduce the construction times and reduce the performance overhead

function clone(parent, child) {
    // Use object instead Create can reduce the process of one more construction in composite inheritance
    child.prototype = Object.create(parent.prototype)
    child.prototype.constructor = child;
}

function Parent() {
    this.name = "parent"
    this.friend = ['1', ',2', '3']
}
Parent.prototype.getName = function () {
    return this.name
}
function Child() {
    Parent.call(this)
    this.friend = "labor"
}
clone(Parent, Child)
Child.prototype.getFriends = function(){
    return this.friend
}

let c1 = new Child()
console.log(c1)  // Child { name: 'parent', friend: 'labor' }
console.log(c1.getName())  // parent
console.log(c1.getFriends()) // labor

Extensions in ES6 also adopts this method

classification
Do not use object The method of create is constructor inheritance and prototype chain inheritance. They are combined into composite inheritance
Use object The method of create is prototype inheritance and parasitic inheritance. Based on this, there is parasitic composite inheritance, which is similar to ES6 extensions

Keywords: Javascript Front-end ECMAScript

Added by Spud_Nic on Sat, 11 Dec 2021 14:30:56 +0200