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

epi*_*ian 16 coffeescript

我试图Error在CoffeeScript中继承本机JS 对象以获取专门的错误类型,但是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
Run Code Online (Sandbox Code Playgroud)

问题似乎是由如何定义生成的JS构造函数引起的.当我没有在CoffeeScript中定义构造函数时:

SimpleError = (function(_super) {

  __extends(SimpleError, _super);

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

  return SimpleError;

})(Error);
Run Code Online (Sandbox Code Playgroud)

当我定义CoffeeScript的构造函数:

SuperConstructorError = (function(_super) {

  __extends(SuperConstructorError, _super);

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

  return SuperConstructorError;

})(Error);
Run Code Online (Sandbox Code Playgroud)

如您所见,return第一种情况的区别很简单.我不明白为什么这会对instanceof行为产生任何影响,因为超级构造函数只是被应用于this对象(即超级构造函数没有被调用new),但是我又不知道很多JS构造函数如何工作= P.

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

知道为什么会发生这种情况,我怎么能避免编写虚拟构造函数只是为了让instanceof操作符正常工作?

谢谢!

更新

So the user matyr answered with a link to the commit where this behavior was introduced, but it doesn't quite explain what is happening here, so i'll try to explain that a little bit in case anyone else wonders why this works this way.

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

function Foo() {
    return {'LOL': 'You fool!'};
}
new Foo() instanceof Foo // -> false
Run Code Online (Sandbox Code Playgroud)

而且还有一个事实,即一些本地的建设者,像Error,Array,String和诸如此类的东西并不需要与被称为new:他们只会返回相应类型的新对象,如果你碰巧忘记它.

最后,将这两个丑陋的东西加在一起,结果就是如果你想让操作员正常工作,你应该记得写class MyError extends Error then constructor: -> super而不是更直观.这是因为CoffeeScript的隐式构造函数将返回父构造函数返回的任何内容,在这种情况下,它将只返回一个新的错误对象,而不是您作为参数传递的对象.好极了!class MyError extends ErrorinstanceofMyErrorreturn Error.apply(this, arguments)this

更新2(2013年2月25日)

这个问题在CoffeeScript 1.5.0中得到修复!= d

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

class MyError extends Error
new MyError instanceof MyError # -> true :)
Run Code Online (Sandbox Code Playgroud)

更新3(2013年3月4日)

Aaand它在1.6.0 = P上消失了

mat*_*tyr 5

无论好坏,return都在 1.3.1中添加了修复#1966(和#2111)。