7

我看到很多这样的代码:

function Base() {}
function Sub() {}
Sub.prototype = new Base();

但是,如果您这样做:

s = new Sub();
print(s.constructor == Sub);

这是错误的。这似乎让我感到困惑,因为 s 的构造函数确实是 Sub。这样做是传统的/更好的吗?

function Base() {}
function Sub() {}
Sub.prototype = new Base();
Sub.prototype.constructor = Sub;

还是真的不重要?

4

3 回答 3

9

'constructor' 并没有像它看起来那样做。除了它的非标准性之外,这也是避免使用它的一个很好的理由——坚持使用 instanceof 和原型。

从技术上讲:“构造函数”不是“s”实例的属性,它是“子”原型对象的属性。当您在 Mozilla 中创建“Sub”函数时,您会得到一个新创建的默认 Sub.prototype 对象,它有一个“构造函数”,出于礼貌,它指向 Sub 函数。

但是,您随后用新的 Base() 替换该原型。带有返回 Sub 的链接的原始默认原型丢失;相反,Sub.prototype 是 Base 的一个实例,没有任何覆盖的“构造函数”属性。所以:

new Sub().constructor===
Sub.prototype.constructor===
new Base().constructor===
Base.prototype.constructor===
Base

...一直到您没有更改其原型的最基本对象。

这样做是传统的/更好的吗?

在处理 JavaScript 对象/类时,没有一个约定;每个库的元类系统的行为都略有不同。我还没有看到手动将“构造函数”写入每个派生类,但如果您真的想要真正的构造函数可用,它似乎是一个很好的解决方案;它还将使代码与不给您“构造函数”的浏览器/引擎兼容。

不过,我会考虑给它一个不同的名称,以避免与现有的和行为不同的“构造函数”属性混淆。

于 2008-12-31T12:47:51.683 回答
3

如果要测试对象是否完全是 Sub 的实例,请使用instanceof运算符:-

print(s instanceof Sub);

如果您想知道一个对象是 Sub 的实例还是 Sub 子类的实例,请使用以下isPrototypeOf方法:-

print(Sub.prototype.isPrototypeOf(s));
于 2008-12-31T11:18:34.140 回答
1

是的,

Sub.prototype.constructor = Sub;

让我们使用 instanceof 但有更好的解决方案。看这里:,GitHub上的TDD JS Inheritance,找到寄生组合继承模式。该代码是 TDD 的,因此您应该能够非常快速地了解它,然后只需更改名称即可开始。这基本上是 YAHOO.lang.extend 使用的(来源:yahoo 员工和作者 Nicholas Zakas 的 Professional JavaScript for Web Developer's,第 2 版,第 181 页)。顺便说一句好书(不以任何方式附属!)

为什么?因为您正在使用的经典模式具有静态引用变量(如果您在基础对象中创建 var arr = [1,2],则所有实例都将具有读/写功能并且将“共享状态”的“arr”!如果您使用构造函数窃取你可以解决这个问题。看我的例子。

于 2009-10-29T15:06:28.720 回答