对本地对象进行子类化:instanceof无法正常工作 [英] Subclassing native objects: instanceof not working properly

查看:128
本文介绍了对本地对象进行子类化:instanceof无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在CoffeeScript中继承原生的JS 对象,以获得专门的错误类型,但我发现 instanceof 不能正常工作如果我没有定义一个构造函数在子类:

 类SimpleError extends错误
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 构造函数。当i 在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;

}错误);

正如你所看到的,区别是一个简单的 return 在第一种情况。我不明白为什么这会使 instanceof 行为有任何区别,因为超级构造函数只是应用于 this object(即超级构造函数不是用 new ),但是我不知道JS构造函数是如何工作的= P

奇怪的是,这种行为似乎只有在子类化本地JS对象时才会发生。如果我的子类CoffeeScript类一切正常工作。



任何想法为什么这可能发生,我怎么可能避免编写虚拟构造函数只是为



更新



因此,用户匹配回答了带有提交的链接,此行为是介绍,但它不能很好地解释这里发生了什么,所以我会尝试解释一下,如果有人想知道为什么这样做这种方式。



主要的问题是这个继承来自JavaScript的讨厌的特性,它允许我们定义一个构造函数,该函数返回除了正在构造的对象之外的对象:

 code> function Foo(){
return {'LOL':'You fool!'};
}
new Foo()instanceof Foo // - > false

还有一个事实,一些本机构造函数,如 / code>,数组 String 和whatnot不需要使用 new :如果你碰巧忘记它,它们将返回相应类型的新对象。



两个丑陋的事情在一起,结果是你应该记住写类MyError extends Error然后构造函数: - > super 而不是更直观的类MyError extends Error 如果你想要 instanceof 使用 MyError 可以正常工作。这是因为CoffeeScript的隐式构造函数只返回父构造函数返回的任何东西,在这种情况下会执行 return Error.apply(this,arguments),这将返回一个新的错误对象,而不是作为 this 参数传递的对象。 Yay!



更新2(2013年2月25日)



此问题已在CoffeeScript 1.5.0中修正! = D



现在扩展本地对象的工作原理如下:

  MyError extends Error 
new MyError instanceof MyError# - > true :)



更新3(2013年3月4日)



Aaand它走了1.6.0 = P

解决方案

无论好坏, return 是在1.3.1上添加以修复< a href =https://github.com/jashkenas/coffee-script/issues/1966 =nofollow>#1966 (and #2111 )。


I'm trying to subclass the native JS Error object in CoffeeScript to get specialized error types, but i found that the instanceof does not work correctly if i don't define a constructor in the subclasses:

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

The problem seems to be caused by how the generated JS constructor functions are defined. When i don't define a constructor in CoffeeScript:

SimpleError = (function(_super) {

  __extends(SimpleError, _super);

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

  return SimpleError;

})(Error);

And when i do define a constructor in CoffeeScript:

SuperConstructorError = (function(_super) {

  __extends(SuperConstructorError, _super);

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

  return SuperConstructorError;

})(Error);

As you can see, the difference is a simple return in the first case. I don't understand why this makes any difference in the instanceof behavior though, as the super constructor is just being applied to the this object (i.e. the super constructor is not being called with new), but then again i don't understand a whole lot of how JS constructors work =P

And the weird thing is that this behavior seems to only happen when subclassing native JS objects. If i subclass CoffeeScript classes everything works as expected.

Any idea of why this might be happening and how could i avoid writing dummy constructors just for the instanceof operator to work correctly?

Thanks!

Update

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.

The main problem is this inherited nasty "feature" from JavaScript which let us define a constructor function that returns an object other than the one being constructed:

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

And there is also the fact that some native constructors, like Error, Array, String and whatnot don't need to be called with new: they will just return a new object of the corresponding type if you happen to forget it.

In the end, add these two ugly things together and the result is that you should remember to write class MyError extends Error then constructor: -> super instead of the more intuitive class MyError extends Error if you want the instanceof operator to work properly with MyError. That's because CoffeeScript's implicit constructor will just return whatever the parent constructor returns, and in this case will do return Error.apply(this, arguments) which will just return a shinny new error object instead of the object you passed as the this argument. Yay!

Update 2 (Feb 25 2013)

This problem was fixed in CoffeeScript 1.5.0! =D

Now extending native objects works as expected:

class MyError extends Error
new MyError instanceof MyError # -> true :)

Update 3 (Mar 04 2013)

Aaand it's gone on 1.6.0 =P

解决方案

For better or worse, the return was added on 1.3.1 to fix #1966 (and #2111).

这篇关于对本地对象进行子类化:instanceof无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆