在线有很多关于JavaScript原型设计和继承的资源。其中大多数使用与此类似的代码:
function Base() {}
function Sub() {}
继承实现如下:
Sub.prototype = new Base();
但我想知道以这种方式实现的继承有什么问题:
Sub.prototype = Base.prototype;
似乎第二个也同样有效。我发现的唯一两个差异(IMO是第二种方法的优势)是:
Base
虚拟实例化
更好,因为实例从未使用过__proto__
属性,而第二个唯一的,这使得
实例清洁工。后者在下面的代码片段中说明:
function Base(){}
Base.prototype.bogus = function(){};
function SubNew(){}
function SubProto(){}
SubNew.prototype = new Base();
SubProto.prototype = Base.prototype;
var sn = new SubNew();
var sp = new SubProto();
console.log(sn);
console.log(sp);
给出:
但我的印象是我在这里错过了一些非常重要的观点。我的问题是:针对第二种方法的情况是什么?
答案 0 :(得分:4)
当您向Sub.prototype
添加新属性时,您不希望它影响Base.prototype
,是吗?那会很破碎。 : - )
使用new Base()
方法意味着您对Sub.prototype
所做的任何更改都会通过"泄漏。到Base.prototype
。
答案 1 :(得分:4)
我会像这样设置
function Base() {}
function Sub() {
// call parent constructor; optional
Base.call(this);
}
Sub.prototype = Object.create(Base.prototype, {constructor: {value: Sub}});
这与util.inherits在node.js
中的工作方式非常相似答案 2 :(得分:3)
如果您使用Sub.prototype = Base.prototype;
,则无法将任何方法添加到Sub.prototype,而不会将它们显示在Base.prototype中,因为它们是同一个对象。
除了构造函数之外,Sub和Base将是完全相同的类。
答案 3 :(得分:2)
当你使用相同的原型时,你不会继承任何东西,你只是制作另一种类型的副本。
如果你在基类型对象中放入任何东西,如果你只是获得原型,它将不会被继承:
function Base(){
this.answer = 42;
}
function SubNew(){}
function SubProto(){}
SubNew.prototype = new Base();
SubProto.prototype = Base.prototype;
var sn = new SubNew();
var sp = new SubProto();
// show result in StackOverflow snippet
document.writeln(sn.answer);
document.writeln(sp.answer);

答案 4 :(得分:0)
基本上,如果您分配prototype
属性,那么您将创建另一个构造函数,该构造函数将创建对同一对象进行原型化的对象,而不是继承,您将通过此示例清楚地看到它:
function Base() { }
function SubType() { }
function YourCase() { }
SubType.prototype = Object.create(Base.prototype);
YourCase.prototype = Base.prototype;
Base.prototype.foo = 1;
SubType.prototype.foo = 2;
YourCase.prototype.foo = 3;
console.log(new Base().foo); // 3 WAT?
console.log(new SubType().foo); // 2
console.log(new YourCase().foo); // 3
如果我们在编辑YourCase.prototype = Base.prototype
时在子类型YourCase.prototype
上使用相同的对象,那么您也在编辑Base.prototype
,因为它们是同一个对象。
这就是为什么你必须使用Object.create(Base.prototype)
或new Base()
来扩展原型。