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
この問題は、生成された 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
最後に、これら 2 つの醜いものを一緒に追加すると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 日)
ああ、それは 1.6.0 ではなくなりました =P