子类化本机对象:instanceof无法正常工作

时间:2012-05-29 19:02:30

标签: coffeescript

我正在尝试将CoffeeScript中的本机JS Error对象子类化以获取专门的错误类型,但是如果我没有在中定义构造函数,我发现instanceof无法正常工作子类:

class SimpleError extends Error
class EmptyConstructorError extends Error
  constructor: ->
class SuperConstructorError extends Error
  constructor: -> 
    super

new SimpleError instanceof SimpleError                     # -> false
new EmptyConstructorError instanceof EmptyConstructorError # -> true
new SuperConstructorError instanceof SuperConstructorError # -> true

问题似乎是由generated JS构造函数的定义方式引起的。当我在CoffeeScript中定义构造函数时:

SimpleError = (function(_super) {

  __extends(SimpleError, _super);

  function SimpleError() {
    return SimpleError.__super__.constructor.apply(this, arguments);
  }

  return SimpleError;

})(Error);

当我在CoffeeScript中定义构造函数时:

SuperConstructorError = (function(_super) {

  __extends(SuperConstructorError, _super);

  function SuperConstructorError() {
    SuperConstructorError.__super__.constructor.apply(this, arguments);
  }

  return SuperConstructorError;

})(Error);

正如您所看到的,在第一种情况下差异很简单return。我不明白为什么这会对instanceof行为产生任何影响,因为超级构造函数只是应用于this对象(即超级构造函数未被{{1}调用但是,我再也不了解JS构造函数的工作原理= P

奇怪的是,这种行为似乎只在子类化本机JS对象时才会发生。如果我将CoffeeScript类子类化,一切都按预期工作。

知道为什么会发生这种情况,我怎么能避免只为new运算符编写虚拟构造函数才能正常工作?

谢谢!

更新

所以用户matyr answered带有引用此行为的提交的链接,但它并没有完全解释这里发生了什么,所以我会尝试解释一下,以防万一其他人想知道为什么这样做。

主要的问题是来自JavaScript的这个继承的令人讨厌的“特性”,它让我们定义一个构造函数,它返回一个不同于正在构造的对象的对象:

instanceof

还有一些本地构造函数,例如function Foo() { return {'LOL': 'You fool!'}; } new Foo() instanceof Foo // -> false ErrorArray以及不需要使用String调用的东西:它们将如果碰巧忘了它,只需返回相应类型的新对象。

最后,将这两个丑陋的东西加在一起,结果就是如果你想让new运算符工作,你应该记得写class MyError extends Error then constructor: -> super而不是更直观的class MyError extends Error适当地使用instanceof。这是因为CoffeeScript的隐式构造函数将返回父构造函数返回的任何内容,在这种情况下将执行MyError,这将只返回一个新的错误对象,而不是您作为return Error.apply(this, arguments)参数传递的对象。耶!

更新2(2013年2月25日)

这个问题was fixed in CoffeeScript 1.5.0! = d

现在扩展本机对象按预期工作:

this

更新3(2013年3月4日)

Aaand已经消失在1.6.0 = P

1 个答案:

答案 0 :(得分:4)

无论好坏,1.3.1上的returnadded以修复#1966(以及#2111)。