JS繼承實現的幾種方式及其優缺點

原型繼承

缺點: 子類實例共享屬性,形成實例間的屬性會相互影響函數

function Parent1() {
  this.name = ['super1']
  this.reName = function () {
    this.name.push('super111')
  }
}
function Child1() {

}
Child1.prototype = new Parent1()
var child11 = new Child1()
var child12 = new Child1()
var parent1 = new Parent1()
child11.reName()
console.log(child11.name, child12.name) // [ 'super1', 'super111' ] [ 'super1', 'super111' ], 能夠看到子類的實例屬性皆來自於父類的一個實例,即子類共享了同一個實例
console.log(child11.reName === child12.reName) // true, 共享了父類的方法

構造函數繼承

缺點: 父類的方法沒有被共享,形成內存浪費this

function Child2() {
  Parent1.call(this)
}

var child21 = new Child2()
var child22 = new Child2()
child21.reName()
console.log(child21.name, child22.name) // [ 'super1', 'super111' ] [ 'super1' ], 子實例的屬性都是相互獨立的
console.log(child21.reName === child22.reName) // false, 實例方法也是獨立的,沒有共享同一個方法

組合繼承

缺點: 父類構造函數被調用兩次,子類實例的屬性存在兩份。形成內存浪費prototype

function Parent3() {
  this.name = ['super3']
}
Parent3.prototype.reName = function() {
  this.name.push('super31')
}
function Child3() {
  Parent3.call(this) // 生成子類的實例屬性(可是不包括父對象的方法)
}
Child3.prototype = new Parent3() // 繼承父類的屬性和方法(反作用: 父類的構造函數被調用的屢次,且屬性也存在兩份形成了內存浪費)
var child31 = new Child3()
var child32 = new Child3()
child31.reName()
console.log(child31.name, child32.name) // [ 'super3', 'super31' ] [ 'super3' ], 子類實例不會相互影響
console.log(child31.reName === child32.reName) //true, 共享了父類的方法

寄生繼承

完美:子類都有各自的實例不會相互影響,且共享了父類的方法code

function Parent4() {
  this.name = ['super4']
}
Parent4.prototype.reName = function() {
  this.name.push('super41')
}
function Child4() {
  Parent4.call(this) // 生成子類的實例屬性(可是不包括父對象的方法)
}
Child4.prototype = Object.create(Parent4.prototype) // 該方法會使用指定的原型對象及其屬性去建立一個新的對象
var child41 = new Child4()
var child42 = new Child4()
child41.reName()
console.log(child41.name, child42.name) //[ 'super4','super41' ] [ 'super4' ], 子類實例不會相互影響
console.log(child41.reName === child42.reName) //true, 共享了父類的方法

ES6 class

和寄生繼承實現的效果一致對象

class Parent5 {
  constructor() {
    this.name = ['super5']
  }
  reName() {
    this.name.push('new 5')
  }
}

class Child5 extends Parent5 {
  constructor() {
    super()
  }
}

var child51 = new Child5()
var child52 = new Child5()
child51.reName()
console.log(child51.name, child52.name) // [ 'super5', 'new 5' ], 子類實例不會相互影響
console.log(child51.reName === child52.reName) //true, 共享了父類的方法
相關文章
相關標籤/搜索