我看到很多像这样的代码:

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;

还是不重要?

有帮助吗?

解决方案

'constructor'不会像它看起来那样做。除了非标准之外,这是避免使用它的一个很好的理由 - 坚持使用instanceof和prototype。

技术上:'构造函数'不是's'实例的属性,它是'Sub'原型对象的属性。当您在Mozilla中创建“Sub”函数时,您将获得一个新创建的默认Sub.prototype对象,该对象具有指向Sub函数的“构造函数”作为礼貌。

但是,然后用新的Base()替换该原型。返回Sub的原始默认原型丢失了;相反,Sub.prototype是Base的一个实例,没有任何重写的'constructor'属性。所以:

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

......一直到最基本的对象,你的原型没有改变。

  

这样做是常规/更好吗?

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

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

其他提示

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

print(s instanceof Sub);

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

print(Sub.prototype.isPrototypeOf(s));

对,

Sub.prototype.constructor = Sub;

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top