继承的本质就是两件事:继承属性和继承方法

看完这篇博客,你将了解:

  1. ES5 代码实现继承
  2. ES6 代码实现继承
  3. js 继承背后的原理

ES5 代码实现继承

ES5 代码两句解决:

  • 继承属性:调用父类构造函数
  • 继承方法:原型链指向父类原型
function Human(name){
    this.name = name
}
Human.prototype.run = function(){
    console.log("我叫"+this.name+",我在跑")
}
function Man(name){
    Human.call(this, name)  // 调用父类构造函数(这里继承属性)
 this.gender = '男'
}

Man.prototype.__proto__ = Human.prototype  // 原型链插入(这里继承方法)
Man.prototype.fight = function(){
console.log('糊你熊脸')
}

注:兼容 IE 的写法( 这里充分利用了 new 这个语法)

var f = function() {}
f.prototype = 父类.prototype
var 子类 = new f()

ES6 代码实现继承

ES6 还是两句代码解决

  • 继承方法:extends
  • 继承属性:super
class Human{
    constructor(name){
        this.name = name
    }
    run(){
        console.log("我叫"+this.name+",我在跑")
        return undefined
    }
}
class Man extends Human{  // 这里继承方法
    constructor(name){
        super(name)  // 这里继承属性
        this.gender = '男'
    }
    fight(){
        console.log('糊你熊脸')
    }
}

js 继承背后的原理

构造函数的 prototype,会成为其实例的 __proto__

var a = new A()
a.__proto__ === A.prototype

如果一个对象,调用了不属于自己定义的方法,那么它一定是在原型链上找到该方法

var a = new Array()
a.push()  // push 是 Array 的方法
a.toString()  // toString 是 "父类" Object 的方法
// toString 是 a 通过原型链找到的方法

可见,js 所谓的继承,其实就是两次以上的原型搜索,比如 toString() 就可以看作是 a 继承的方法

上面的代码正是基于这个原理,使得子类得以调用父类的方法

继承前:子类构造函数.prototype.__proto__ = Object.prototype

继承后:子类构造函数.prototype.__proto__ = 父类构造函数.prototype