ES5
先看看ES5的組合繼承:
//定義 父構(gòu)造函數(shù)Dog()
function Dog(name) {
this.name = name
}
//向Dog的原型對象添加eat方法
Dog.prototype.eat = function () {
console.log(this.name + '吃肉')
}
var lasi = new Dog('拉斯')
lasi.eat() //拉斯吃肉
//定義 子構(gòu)造函數(shù)Husky(),實現(xiàn)繼承
function Husky(name) {
// call() 改變this指向,這里從 指向Dog的實例 變?yōu)?指向Husky的實例
// 從而繼承了父類的實例屬性
Dog.call(this, name)
}
// 把 Dog實例 賦值 給 Husky原型對象,Husky.prototype就能找到eat()方法
//這就實現(xiàn)了方法的繼承
Husky.prototype = new Dog()
// 再添加constructor屬性
Husky.prototype.constructor = Husky
// 給Husky添加新方法
Husky.prototype.bark = function () {
console.log(this.name + ':嗚嗚嗚嗚~')
}
var ergou = new Husky('二狗')
ergou.eat() // 二狗吃肉
ergou.bark() // 二狗:嗚嗚嗚嗚~
組合繼承比較直觀,且較好的實現(xiàn)的繼承。但其缺點在于實現(xiàn)繼承的過程中,調(diào)用了2次 Dog()。下面再介紹最佳方案——寄生式組合繼承。
function Dog(name) {
this.name = name
}
Dog.prototype.eat = function () {
console.log(this.name + " eat meat")
}
const lasi = new Dog('Lasi')
lasi.eat() // Lasi eat meat
function Husky(name) {
Dog.call(this, name)
}
// 盜取父類構(gòu)造函數(shù)的原型(方式一)
function steal(obj) {
function F() { }
F.prototype = obj
return new F()
}
Husky.prototype = steal(Dog.prototype)
// 盜取父類構(gòu)造函數(shù)的原型(方式二)
// Husky.prototype = Object.create(Dog.prototype)
// 添加constructor屬性
Husky.prototype.constructor = Husky
Husky.prototype.bark = function () {
console.log(this.name + ": wu~~~~~")
}
const ergou = new Husky('Ergou')
ergou.eat() // Ergou eat meat
ergou.bark() // Ergou: wu~~~~~
es5實現(xiàn)繼承的代碼顯得比較冗長和混亂,為此,ES6引入class關(guān)鍵字。class是新的基礎(chǔ)性語法糖結(jié)構(gòu),其背后本質(zhì)上仍然是原型和構(gòu)造函數(shù)的概念。
ES6
class Dog{
constructor(name){
this.name = name
}
eat(){
console.log(this.name + '吃肉')
}
}
class Husky extends Dog{
constructor(name){
super(name)
}
bark(){
console.log(this.name + ':嗚嗚嗚')
}
}
var ergou = new Husky('二狗')
ergou.eat() // 二狗吃肉
ergou.bark() // 二狗:嗚嗚嗚
ES6的繼承確實很簡潔!