JS 继承的原理实现(ES5和ES6)

ES5

先看看ES5的组合继承

//定义 父构造函数Dog()
function Dog(name) {
    this.name = name
}
//向Dog的原型对象添加eat方法
Dog.prototype.eat = function () {
    console.log(this.name + '吃肉')
}

var lasi = new Dog('拉斯')
lasi.eat()  //拉斯吃肉

//定义 子构造函数Husky(),实现继承
function Husky(name) {
    // call() 改变this指向,这里从 指向Dog的实例 变为 指向Husky的实例
    // 从而继承了父类的实例属性
    Dog.call(this, name)
}
// 把 Dog实例 赋值 给 Husky原型对象,Husky.prototype就能找到eat()方法
//这就实现了方法的继承
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()  // 二狗:呜呜呜呜~

组合继承比较直观,且较好的实现的继承。但其缺点在于实现继承的过程中,调用了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)
}

// 盗取父类构造函数的原型(方式一)
function steal(obj) {
    function F() { }
    F.prototype = obj
    return new F()
}
Husky.prototype = steal(Dog.prototype)

// 盗取父类构造函数的原型(方式二)
// 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实现继承的代码显得比较冗长和混乱,为此,ES6引入class关键字。class是新的基础性语法糖结构,其背后本质上仍然是原型和构造函数的概念。

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的继承确实很简洁!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。