1.借助構造函數實現繼承
function Parent() { this.name = 'parent' } Parent.prototype.say = function () { // 不能被繼承 this.say = function() { console.log('hello'+ this.name) } } function Child() { Parent.call(this) this.type = 'child' } console.log(new Child) // 沒有參數可以不寫最后的()
call方法改變了函數運行的上下文(this的指向,指向了Child實例化的對象引用),將父級構造函數的this指向子類構造函數的實例上去。執行時父類的方法和屬性都掛載到Child類的實例上
缺點:
父類的原型對象上有屬性和方法不能被子類繼承
?
2.借助原型鏈實現繼承
function Parent2() { this.name = 'parent2' this.list = [1,2,5] } Parent2.prototype.say = function () { // 不能被繼承 this.say = function() { console.log('hello'+ this.name) } } function Child2() { this.type = 'child' } Child2.prototype = new Parent2() var c21 = new Child2() var c22 = new Child2()// 缺點 c21.list.push(6) console.log(c22.list) // [1, 2, 5, 6]
prototype就是讓Child的實例可以訪問到原型鏈上
根據原型鏈
由 Child2.prototype = new Parent2()
和 c21.__proto__ === Child2.prototype
得 c21.__proto__ 指向了new Parent2()
所以 c21.__proto__.__proto__ 與 new Parent2().__proto__為同一個對象
又因為 new Parent2().__proto__ === Parent2.prototype
所以c21.__proto__.__proto__指向 Parent2.prototype
缺點:
原型鏈中的原型對象是公用的
?
3.組合繼承
function Parent3() { this.name = 'parent3' this.list = [1,2,5] } function Child3() { Parent3.call(this) this.type = 'child3' } Child3.prototype = new Parent3() var c3 = new Child3()
缺點:
Parent3()執行了兩次,一次在Child3()里面,一次是給Child2.prototype賦值時
?
?
4. 組合繼承優化1
function Parent4() { this.name = 'parent4' this.list = [1,2,5] } function Child4() { Parent5.call(this) this.type = 'child4' } Child4.prototype = Parent4.prototype var c4 = new Child4()// 缺點 console.log(c31.__proto__.constructor) // Parent4
缺點:
因為Child4.prototype = Parent4.prototype,所以Child4沒有構造器,是從父類繼承的
?
?
5. 組合繼承優化2
function Parent5() { this.name = 'parent5' this.list = [1,2,5] } function Child5() { Parent5.call(this) this.type = 'child5' } Child5.prototype = Object.create(Parent5.prototype) Child5.prototype.constructor = Child5 var c5 = new Child5()
缺點:
。。。可能就是比較麻煩吧
?
6.ES6實現繼承(與5的效果相同)
class Animal {constructor(name='animal') {this.name = name}eat () {console.log('I can eat')} }class Dog extends Animal {constructor(name='dog') {super(name)}bark() {console.log('bark')} }let dog1 = new Dog let dog2 = new Dog('dd')
?