js 理解继承

Js里的继承通常就是原型链继承。即实现A的原型的原型为B的原型,则A继承B。
首先须要了解下实例,构造函数,原型对象之间是怎样的关系。实例为从构造函数new获得的新对象,它有__proto__能够指向原型对象,经过instanceof方法能够判断实例的构造函数类型;构造函数的prototype指向原型对象,原型对象有constructor指向构造函数。详细了解能够参考http://www.noobyard.com/article/p-wkalkhrk-gr.htmlsegmentfault

了解了三者关系以后,咱们须要作的其实就是更改A的原型。让新的原型知足两个条件:函数

  1. 新原型的原型指向被继承者B
  2. 新原型的构造函数指向A
function A() {
}
function B() {
}
B.prototype.say = function(){console.log('say')}

// 准备一个中间变量
function C(){}
// 从新设置C的原型为B的原型
C.prototype = B.prototype
// 建立一个实例c,此时c的原型是B的原型
var c = new C()
// 设置实例c的构造函数指向A,
c.constructor = A

// 上述步骤后A新的原型对象c建立完成,它的原型指向B,构造函数指向A
A.prototype = c
// 此时原型链为 new A()._proto__ (c) => B.prototype => Object.prototype => null
console.log(new A(), new B())

image.png

有的人可能会奇怪,为何不能直接使用A.prototype = B.prototype,这样的话至关于A,B共用一个原型对象,A在原型的更改会直接影响B,不符合继承要求,子类没法独自扩展;并且,A的原型对象的构造函数此时指向的是B,意味着实例没法从新访问构造函数。spa

function A() {
}
function B() {
}
B.prototype.say = function(){console.log('say')}
A.prototype = B.prototype
A.prototype.sayA = function(){console.log('sayA')}
console.log(new B().sayA()) // sayA
console.log(new A().__proto__.constructor) // function B() {}

常见的介绍js继承的文章有不少,里面通常介绍了诸如原型继承,构造函数继承,组合继承等等,以及不一样方式的缺点与优势,看的懵懵的,但咱们只要知道这些方式的本质就是建立原型链(A的原型的原型为B的原型),那些方法其实就很好理解了。要作到继承直接使用A.prototype.__proto__ = B.prototype 或者Object.setPrototypeOf(A.prototype, B.prototype)也彻底能够,可是要注意是否支持。详细了解参考MDN https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOfprototype