17

ErrorCoffeeScript でネイティブ 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また、 、 などの一部のネイティブ コンストラクターはArrayStringで呼び出す必要がないという事実もありますnew。それらは、たまたまそれを忘れた場合に、対応する型の新しいオブジェクトを返すだけです。

class MyError extends Error then constructor: -> super最後に、これら 2 つの醜いものを一緒に追加するとclass MyError extends Errorinstanceofオペレーターが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

4

1 に答える 1

5

良くも悪くも、#1966 (および#2111 )を修正するために 1.3.1 にreturn追加れました。

于 2012-05-29T22:58:11.970 に答える