First, prototype chain inheritance

/ / parent class
Animal.prototype.sleep = function() {
	console.log(`The ${this.name} sleepping now`);
}

function Animal(name){
  this.name = name || 'animal';
  this.playList = ['ball'.'water']}/ / subclass

function Dog(){}/ / inheritance
Dog.prototype = new Animal();
/ / correct constructor
Dog.prototype.constructor = Dog;

var wangwang = new Dog();
var doudou = new Dog();

console.log(wangwang instanceof Dog) // true
console.log(doudou instanceof Animal) // true
console.log(wangwang instanceof Dog) // true
console.log(doudou instanceof Animal) // true

wangwang.sleep() // 'animal sleepping now'
doudou.sleep() // 'animal sleepping now'

console.log(wangwang.playList) // ['ball','water']
console.log(doudou.playList) // ['ball','water']

wangwang.playList.push('run')

console.log(wangwang.playList) // ["ball", "water", "run"]
console.log(doudou.playList) // ["ball", "water", "run"]
Copy the code

Conclusion: A subclass can inherit the attributes of the parent class and the attributes of the parent class prototype by changing the prototype to point to the parent class instance object. The advantages are as follows: 1. The implementation is easy, and the code is simple and easy to understand

Disadvantages: 1. When a subclass creates an instance, it cannot pass parameters to its parent class. 2

Constructor inheritance

/ / parent class
Animal.prototype.sleep = function(){
  console.log(`The ${this.name} sleepping now`)}function Animal(name, sex){
  this.name = name;
  this.sex = sex;
  this.playList = ['ball'.'water'];
}

/ / subclass
function Dog(name, sex, age){
  Animal.call(this, name, sex);
  this.age = age;
}

var wangwang = new Dog('wangwang'.'male'.19);
var doudou = new Dog('doudou'.'female'.11);

console.log(wangwang instanceof Dog) // true
console.log(doudou instanceof Animal) // false
console.log(wangwang instanceof Dog) // true
console.log(doudou instanceof Animal) // false

console.log(wangwang.playList) // ['ball','water']
console.log(doudou.playList) // ['ball','water']

wangwang.playList.push('run')

console.log(wangwang.playList) // ["ball", "water", "run"]
console.log(doudou.playList) // ["ball", "water"]

wangwang.sleep() / / an error
doudou.sleep() / / an error
Copy the code

Conclusion: When the attribute of the subclass completely overwrites the attribute of the parent class, we can use call to borrow the constructor of the parent class to realize the advantages of inheritance. It solves the two disadvantages of inheritance in the prototype chain: 1. The subclass can pass parameters to the parent class

Disadvantages: 1, the instance of the subclass is only the instance of the subclass, not the instance of the parent class. 2, the attributes of the prototype of the parent class will not be inherited by the subclass

3. Combinatorial inheritance (prototype chain and constructor combination)

/ / parent class
Animal.prototype.sleep = function(){
  console.log(`The ${this.name} sleepping now`);
}

function Animal(name, sex){
  this.name = name;
  this.sex = sex;
  this.playList = ['ball'.'water'];
}

/ / subclass
function Dog(name, sex, age) {
	Animal.call(this, name, sex);
  this.age = age;
}

// Change the subclass prototype
Dog.prototype = new Animal();

/ / correct constructor
Dog.prototype.constructor = Dog;

var wangwang = new Dog('wangwang'.'male'.19);
var doudou = new Dog('doudou'.'female'.11);

console.log(wangwang instanceof Dog) // true
console.log(doudou instanceof Animal) // true
console.log(wangwang instanceof Dog) // true
console.log(doudou instanceof Animal) // true

console.log(wangwang.playList) // ['ball','water']
console.log(doudou.playList) // ['ball','water']

wangwang.playList.push('run')

console.log(wangwang.playList) // ["ball", "water", "run"]
console.log(doudou.playList) // ["ball", "water"]

wangwang.sleep() // wangwang sleepping now
doudou.sleep() // doudou sleepping now
Copy the code

Conclusion: The advantages of combination inheritance of prototype chain inheritance and constructor inheritance are integrated: A subclass can pass parameters to its parent class. 2. When a parent class has a reference type in its attribute, it does not cause the subclass instance to share the attribute

Disadvantages: 1, memory consumption, subclass every time to generate instances, will execute a parent class function, code reuse principle is not implemented in place

Iv. Inheritance of the original type

// A bit of expansion (from a book I can't remember)
With prototype, you can create a new object from an existing object without creating a new custom object type.
function inheritObject(o){
  // Declare a transition object
  function F(){}
  // The prototype of the transition object points to the parent object
  F.prototype = o;
  // Returns an instance of the transition object whose prototype inherits the parent object
  return new F();
}
Copy the code

Conclusion: This approach is actually very similar to class inheritance, but more reflects a kind of encapsulation idea. We imagine the transition function F as a subclass, and the object O as an instance of the parent class function. Therefore, the problems of this approach and class inheritance have the same problems.

Parasitic inheritance

// Original type method
function inheritObject(o){
  function F(){}

  F.prototype = o;

  return new F();
}

// Parasitic inheritance
/** * params: obj---- instance */
function parasitic(obj) {
  // Create new objects by prototyping
  var o = inheritObject(obj);
  // Extend new attributes
  o.fn = function() {}
  // Returns the expanded new object
  return o;
}
Copy the code

Conclusion: Encapsulate the method of the original type inheritance again, so that the new object not only inherits the attributes and methods of the parent class, but also extends some methods itself, but the problem of class inheritance still exists and has not been solved

The Holy Grail mode

// Core method
function inherit(Origin, Target){
  function F(){}
  
  F.prototype = Origin.prototype;
  
  Target.prototype = new F();
  
  / / correct constructor
  Target.prototype.constructor = Target
}

/ / parent class
Animal.prototype.sleep = function(){
  console.log(`The ${this.name} sleepping now`)}function Animal(name, sex){
  this.name = name;
  this.sex = sex;
  this.playList = ['ball'.'water']}/ / subclass
function Dog(name, sex, age){
  Animal.call(this, name, sex);
  this.age = age;
}

// Implement inheritance
inherit(Animal, Dog);

var wangwang = new Dog('wangwang'.'male'.19);
var doudou = new Dog('doudou'.'female'.11);

console.log(wangwang.playList) // ["ball", "water"]
console.log(doudou.playList) // ["ball", "water"]

wangwang.playList.push('jump')

console.log(wangwang.playList) // ["ball", "water", "jump"]
console.log(doudou.playList) // ["ball", "water"]

wangwang.sleep() // wangwang sleepping now
Copy the code

Summary: 1, this pattern: are there any other name or writing on the net, but look closely, implementation principle is the same as 2, this way of inheritance is combined with the original type of inheritance and prototype chain inheritance way, in the holy grail mode inheritance, the original type inherits the parameters in the object is no longer a common object, and become the prototype object; By changing the prototype of the mediation function to point to the parent function prototype and the subclass to point to the instance of the mediation function, the subclass is associated with the parent class. At the same time, modifying the constructor of the subclass to implement inheritance also removes most of the defects mentioned above. At present, this inheritance method is relatively good.