Coffeescript 子类化本机对象:instanceof无法正常工作
我试图在CoffeeScript中对本机JSCoffeescript 子类化本机对象:instanceof无法正常工作,coffeescript,Coffeescript,我试图在CoffeeScript中对本机JSError对象进行子类化,以获得专门的错误类型,但我发现如果在子类中未定义构造函数,instanceof无法正常工作: class SimpleError extends Error class EmptyConstructorError extends Error constructor: -> class SuperConstructorError extends Error constructor: -> super
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
这个问题似乎是由如何定义构造函数引起的。当我没有在CoffeeScript中定义构造函数时:
SimpleError = (function(_super) {
__extends(SimpleError, _super);
function SimpleError() {
return SimpleError.__super__.constructor.apply(this, arguments);
}
return SimpleError;
})(Error);
SuperConstructorError = (function(_super) {
__extends(SuperConstructorError, _super);
function SuperConstructorError() {
SuperConstructorError.__super__.constructor.apply(this, arguments);
}
return SuperConstructorError;
})(Error);
当我在CoffeeScript中定义构造函数时:
SimpleError = (function(_super) {
__extends(SimpleError, _super);
function SimpleError() {
return SimpleError.__super__.constructor.apply(this, arguments);
}
return SimpleError;
})(Error);
SuperConstructorError = (function(_super) {
__extends(SuperConstructorError, _super);
function SuperConstructorError() {
SuperConstructorError.__super__.constructor.apply(this, arguments);
}
return SuperConstructorError;
})(Error);
如您所见,在第一种情况下,区别在于一个简单的返回。我不明白为什么这会对instanceof
行为产生任何影响,因为超级构造函数只是应用于这个对象(也就是说,超级构造函数不是用new
调用的),但我还是不明白JS构造函数是如何工作的
奇怪的是,这种行为似乎只有在对本机JS对象进行子类化时才会发生。如果我将CoffeeScript类划分为子类,那么一切都会按预期进行
知道为什么会发生这种情况吗?我如何避免只为instanceof
操作符的正确工作而编写虚拟构造函数
谢谢
更新
因此,用户matyr提供了一个指向提交的链接,其中引入了这种行为,但它并不能完全解释这里发生了什么,所以我将尝试解释一下,以防其他人想知道为什么会这样
主要问题是继承了JavaScript的这一令人讨厌的“特性”,它允许我们定义一个构造函数,该构造函数返回一个与正在构造的对象不同的对象:
function Foo() {
return {'LOL': 'You fool!'};
}
new Foo() instanceof Foo // -> false
还有一个事实是,一些本机构造函数,如Error
、Array
、String
等等,不需要用new
调用:如果您碰巧忘记了它,它们只会返回相应类型的新对象
最后,将这两个丑陋的东西加在一起,结果是,如果您希望instanceof
操作符与MyError
一起正常工作,您应该记住编写类MyError extends Error然后编写构造函数:->super
,而不是更直观的类MyError extends Error
。这是因为CoffeeScript的隐式构造函数将只返回父构造函数返回的任何内容,在本例中,将执行返回错误。apply(this,arguments)
将只返回一个新的错误对象,而不是作为this
参数传递的对象。耶
更新2(2013年2月25日)
这个问题=D
现在,扩展本机对象可以按预期工作:
class MyError extends Error
new MyError instanceof MyError # -> true :)
更新3(2013年3月4日)
aa而且它是在1.6.0=p上运行的不管是好是坏,返回的
是在1.3.1上修复的(和)。奇怪的是,你的第一块代码在Chrome、Canary、Safari和Firefox中对我有效。我遗漏了什么吗?所谓的工作,我的意思是它们都像预期的那样返回true。@Sandro这很奇怪:s。在这个链接中,它也适用于我,但奇怪的是JSFIDLE生成的代码似乎与Try CoffeeScript生成的代码不同。查看启用开发人员工具以查看代码的情况,然后。现在这变得更加令人困惑:SMy最初猜测JSFIDLE使用的是旧版本的CoffeeScript,而最新版本破坏了这一功能。这个更新的JSFIDLE也使用了最新的CoffeeScript JS文件。CoffeeScript changelog表示对super
工作方式的一些更改,因此可能与此相关。如果您访问irc.freenode.net#coffeescript并在那里提及此内容,可能会更容易一些?谢谢您的链接!我想我现在明白了这种改变的动机。但我认为这些JS的肮脏通过CS泄露是有点不幸的。我真的希望,如果类MyError扩展了Error
,那么MyError的新MyError实例
。必须将其定义为类MyError扩展了错误,然后构造函数:->super
似乎非常不合适。我真的不知道为什么有人想要/需要从JS或CS:S中的构造函数返回一个不同的对象(即,我不理解在CS中实现这两个问题所要求的东西的必要性)。如果你感兴趣,我在:D中对此展开了一个问题/讨论