js继承中的组合继承和寄生组合继承有什么区别呢?js中的继承分为两个部分,对实例的继承和对原型的继承。可以用原型来继承公用的属性和方法,当原型上的属性和方法改变时,继承关系链上的所有对象都将受到影响;用实例来继承特有的属性和方法,当实例上的属性和方法发生改变时,继承关系链上的所有对象互不影响。
组合继承
1 | function Sup(grade){ |
运行结果如下
可以看到实例上确实已经有了继承自Sup
的grade
属性和由Sub
产生的name
属性,在实例上执行sayGrade
方法也能正确打印出结果。但可以看到由于Sup
构造函数实例化了两次,在Sub
的原型上也出现了grade
属性。由于在实例上获取属性时会按原型链逐级往上找,而在实例上就已经获取到了grade
属性,所以通常情况下原型上的这个属性不会生效,拥有这个“多余的”属性也无伤大雅。但在某些情况下会造成错误,例如删除实例上的grade
属性,实际上还能访问到,此时获取到的是原型上的属性。
问题就出在第一次的new Sup('一3班')
上,只是为了继承原型上的实例和方法其实不必要执行该方法,寄生组合继承就可以解决这个问题。
寄生组合继承
1 | function Sup(grade){ |
运行结果如下
可以看到,Sub
的原型上已经没有grade
属性,这是因为Object.create(Sup.prototype)
方法返回一个以Sup.prototype
为原型的对象,而不用执行Sup
方法。
显然寄生组合继承要比组合继承更加合理。