Prototype chain inheritance

function Parent () {
  this.name = 'wyt'
  this.age = 300
  this.array = [1.2.3]
}

Parent.prototype.getInfo = function () {
  console.log(this.name, this.age)
}

function Child () {
  this.type = 'child'
}

/** New Parent() returns an object named obj: obj = {name: 'wyt', age: 300, array: [1, 2, 3]} Assign this object to child.prototype so that instances of Child can access its internal property values through the prototype chain. At the same time, when new, the obj.__proto__ property will point to Parent. Prototype, equivalent to: obj = {name: 'wyt', age: 300, array: [1, 2, 3], __proto__: Parent.prototype} So attributes on the Parent prototype can also be accessed by instances of Child
Child.prototype = new Parent()

Var son = {} son.__proto__ = child.prototype child.apply (son) */
var son = new Child()

son.getInfo()
console.log(son)
Copy the code

Existing problems:

  1. The parent classParentIn theAttributes of a reference typeBeing modified by an instance of one of the subclasses causes the modified properties of all the other subclasses to change as well
  2. Instances of subclasses cannot pass arguments when created

The occurrence of the first problem is as follows:

var obj1 = new Child()
var obj2 = new Child()
console.log(obj1.array)  / / [1, 2, 3]
console.log(obj2.array)  / / [1, 2, 3]
obj1.array.push(4)
console.log(obj1.array)  // [1, 2, 3, 4]
// We don't really want to change obj2.array, but it has been changed here too, which is not what we want
console.log(obj2.array)  // [1, 2, 3, 4]
Copy the code

Why causes this problem:

Prototype = new Parent(); new Parent() creates a shallow copy of an object, and the properties inside the object are not affected. The address of the reference type is stored in the object, so changing the reference type value affects the property value on all subclass instances.

Constructor inheritance

Constructor inheritance is implemented primarily by borrowing a call.

function Parent () {
  this.name = 'wyt'
  this.age = 300
  this.array = [1.2.3]
}

Parent.prototype.getInfo = function () {
  console.log(this.name, this.age)
}

function Child () {
  this.type = 'child'
  Child this.fun = Parent this.fun() delete this.fun */
  Parent.call(this)}var son = new Child()

console.log(son)
son.getInfo()     / / complains
Copy the code

Existing problems:

  1. Unable to inherit properties from the stereotype, such as the above callson.getInfo()I’m not gonna find itgetInfoMethod error.

Combination of inheritance

Simply combine the above two inheritance methods.

function Parent () {
  this.name = 'wyt'
  this.age = 300
  this.array = [1.2.3]
}

Parent.prototype.getInfo = function () {
   console.log(this.name, this.age)
}

function Child () {
  this.type = 'child'
  Parent.call(this)
}

Child.prototype = new Parent()

var son = new Child()

son.getInfo()
console.log(son)
Copy the code

Existing problems:

  1. ParentIt is executed twice, first when call is called and then again when new Parent() is called

Primary inheritance

Just borrow the object.create () method.

var parent = {
  name: 'wyt'.age: 300.friends: ['kyh'.'lxl'.'szf'].getInfo: function () {
    console.log(this.name, this.age)
  }
}

Var son = {} son.__proto__ = parent */
var son = Object.create(parent)

console.log(son)
son.getInfo()
Copy the code

Existing problems:

  1. Attributes of reference type in the parent object are modified together because of shallow copy, just like archetypal chain inheritance
var obj1 = Object.create(parent)
var obj2 = Object.create(parent)
console.log(obj1.friends)  // ['kyh', 'lxl', 'szf']
console.log(obj2.friends)  // ['kyh', 'lxl', 'szf']
obj1.friends.push('lp')
console.log(obj1.friends)  // ['kyh', 'lxl', 'szf', 'lp']
console.log(obj2.friends)  // ['kyh', 'lxl', 'szf', 'lp']
Copy the code

Parasitic inheritance

Just the name is looking at a little bluffing feeling, in fact, is simply in the original type of inheritance above the encapsulation, strengthen the original shallow copy of some ability, but it is a shallow copy, so the problem of shallow copy it has not been solved.

var parent = {
  name: 'wyt'.age: 300.friends: ['kyh'.'lxl'.'szf'].getInfo: function () {
    console.log(this.name, this.age)
  }
}

// Simply encapsulates the original inheritance and expands the channel for adding attributes
function clone (obj) {
  var res = Object.create(parent)
  res.getName = function () {
    console.log(this.name)
  }
  return res
}

var son = clone(parent)
Var son = object.create (parent, {getName: {value: function () {console.log(this.name)}}}) */

console.log(son)
son.getInfo()
son.getName()
Copy the code

Existing problems:

  1. It still doesn’t solve the problem of primary inheritance
var obj1 = clone(parent)
var obj2 = clone(parent)
console.log(obj1.friends)  // ['kyh', 'lxl', 'szf']
console.log(obj2.friends)  // ['kyh', 'lxl', 'szf']
obj1.friends.push('lp')
console.log(obj1.friends)  // ['kyh', 'lxl', 'szf', 'lp']
console.log(obj2.friends)  // ['kyh', 'lxl', 'szf', 'lp']
Copy the code

Parasitic combinatorial inheritance

It’s the best inheritance, but it’s actually a combination of combinatorial inheritance and parasitic inheritance.

function Parent () {
  this.name = 'wyt'
  this.age = 300
  this.array = [1.2.3]
}

Parent.prototype.getInfo = function () {
  console.log(this.name, this.age)
}

function Child () {
  this.type = 'child'
  Parent.call(this)}/** Change the value of child.prototype to the Object returned by object.create () so that instances of Child can access properties on the Parent prototype. Prototype var obj = {} obj.__proto__ = Parent. Prototype Child. Prototype = obj */
Child.prototype = Object.create(Parent.prototype)

/ * * step will make the Child. The prototype. The constructor is a Parent, Child actually here refers to the return on the prototype chain inheritance and combination of above inheritance, Child. The prototype. The constructor will become the Parent simple point: Var obj = new Child() console.log(obj instanceof Child) // true
Child.prototype.constructor = Child

Child.prototype.getType = function () {
  console.log(this.type)
}

var son = new Child()

console.log(son)
son.getInfo()
son.getType()
var obj1 = new Child()
var obj2 = new Child()
console.log(obj1.array)  / / [1, 2, 3]
console.log(obj2.array)  / / [1, 2, 3]
obj1.array.push(4)
console.log(obj1.array)  // [1, 2, 3, 4]
console.log(obj2.array)  / / [1, 2, 3]
Copy the code

A small summary

  1. Prototype chain inheritance refers to an instance of child.prototype that points to Parent.

  2. Constructor inheritance adds a call to the call() method inside the Child constructor.

  3. Combinatorial inheritance is simply 1 + 1 = 2, a combination of the first two.

  4. Primitive inheritance is no different from creating an Object with object.create ().

  5. Create () creates an Object with some custom attributes. The second argument to object.create () can also be used to create an Object.

  6. Parasitic combined, the combination with parasitic combines, then change the Child. The prototype. The value of the constructor allows the instanceof to correct judgment.

  7. Parasitic combination inheritance is the best inheritance among all inheritance methods.

  8. To make it easy to inherit, learn the following:

    • Prototype and prototype chain
    • New and object.create () implementation principles
    • Implementation principle of Apply and Call