共享原型
- 通过将子类(实例的构造函数)指向父类(原型链上的原型),然后通过原型链的寻找实现继承
- 但是这样会导致子类和父类指向同一个地址空间,子类的修改时也会父类的修改
function Father() {}
function Son() {}
Father.prototype.Name = 'Father-prototype-Name'
Son.prototype = Father.prototype
var son = new Son()
console.log(Son.prototype,Father.prototype)
Son.prototype.Name = 'modify-Name' // 修改子类(Son原型)上属性
console.log(Son.prototype,Father.prototype)
)
圣杯模式
- 通过创建一个对象,然后将该对象构造函数的原型(F.prototype)指向父类(Origin.prototype),再将子类的原型(Target.prototype)指向此对象(new F())
function inherit(Target,Origin) {
// Target extends Origin
var F = Function(){}
F.prototype = Origin.prototype
Target.prototype = new F()
Target.prototype.constructor = Target // 记录实列化对象的构造函数-子类
Target.prototype.uber = Origin.prototype // 记录继承的父类
}
通过立即执行函数将 函数F 私有化
var inherit = (function(){
var F = function(){}
return function(Target,Origin) {
F.prototype = Origin.prototype
Target.prototype = new F()
Target.prototype.constructor = Target
Target.prototype.uber = Origin.prototype
}
})()
未继承时关系如下图所示
-
继承后关系如下图所示
-
那可以将
F.prototype = Origin.prototype
和Target.prototype = new F()
互换位置吗 ?- 显然是不可以的,因为这样Target.prototype 指向实例化匿名对象,因为此时
函数F
的prototype还未修改,所以这时候创建的 实例化对象的__proto__属性指向Object.prototype,而非Origin.prototype 如下图所示
- 显然是不可以的,因为这样Target.prototype 指向实例化匿名对象,因为此时
总结
- javaScript的继承是通过原型链上的原型实现的,需要注意的是prototype属性它指向的是一个地址空间,还有
F.prototype = Origin.prototype
和Target.prototype = new F()
的先后问题