我想继承原生JS Error
在CoffeeScript的对象,以获取专业的错误类型,但我发现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
这个问题似乎被如何引起生成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
对象(即超级构造函数没有被调用new
),但随后再次我不明白一大堆的JS构造函数是如何工作= P
而奇怪的是,这种行为似乎继承原生JS对象时才会发生。 如果我继承的CoffeeScript类一切正常。
任何想法,为什么这可能发生,我怎么能避免编写虚拟构造函数只是为的instanceof
操作才能正常工作?
谢谢!
更新
因此,用户matyr 回答一个链接到介绍这种行为犯,但它并不完全解释这里发生了什么,所以我会尽力解释说,如果任何人奇迹一点点,为什么这这种方式工作。
主要的问题是这样的继承讨厌的“功能”从JavaScript这让我们定义返回一个比其他的物体正在兴建一个构造函数:
function Foo() {
return {'LOL': 'You fool!'};
}
new Foo() instanceof Foo // -> false
而且还有一个事实,即一些本地的建设者,如Error
, Array
, String
和诸如此类的东西并不需要用被称为new
:他们只会返回相应类型的新对象,如果你碰巧忘记它。
最后,一起加入这两个丑陋的东西,其结果是,你应该记得写class MyError extends Error then constructor: -> super
而不是更直观的class MyError extends Error
,如果你想要instanceof
运算符与正常工作MyError
。 这是因为CoffeeScript中的隐式构造函数将只返回无论父构造回报,在这种情况下,将不return Error.apply(this, arguments)
将只返回一个新的晶灵错误对象,而不是你作为传递的对象this
说法。 好极了!
更新2(2013年2月25日)
此问题已修复的CoffeeScript 1.5.0 ! = d
现在扩展原生对象按预期工作:
class MyError extends Error
new MyError instanceof MyError # -> true :)
更新3(2013年3月4日)
AAAND它的消失在1.6.0 = P