Unterklassen von nativen Objekten: Instanceof funktioniert nicht richtig

Ich versuche, die native JS zu unterordnenError Objekt in CoffeeScript, um spezialisierte Fehlertypen zu erhalten, aber ich fand, dass dieinstanceof funktioniert nicht richtig, wenn ich keinen Konstruktor in den Unterklassen definiere:

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

Das Problem scheint dadurch verursacht zu werden, wie diegeneriert JS Konstruktorfunktionen sind definiert. Wenn ichnicht Definieren Sie einen Konstruktor in CoffeeScript:

SimpleError = (function(_super) {

  __extends(SimpleError, _super);

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

  return SimpleError;

})(Error);

Und wenn ichtun Definieren Sie einen Konstruktor in CoffeeScript:

SuperConstructorError = (function(_super) {

  __extends(SuperConstructorError, _super);

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

  return SuperConstructorError;

})(Error);

Wie Sie sehen, ist der Unterschied einfachreturn im ersten Fall. Ich verstehe nicht, warum das einen Unterschied machtinstanceof Verhalten jedoch, da der Superkonstruktor nur auf die angewendet wirdthis object (d. h. der Superkonstruktor wird nicht mit aufgerufennew), aber andererseits verstehe ich nicht viel darüber, wie JS-Konstruktoren arbeiten = P

Und das Seltsame ist, dass dieses Verhalten anscheinend nur auftritt, wenn native JS-Objekte unterklassifiziert werden. Wenn ich CoffeeScript-Klassen untergeordnet habe, funktioniert alles wie erwartet.

Irgendeine Idee, warum dies passieren könnte und wie ich vermeiden könnte, Dummy - Konstruktoren nur für das zu schreibeninstanceof Betreiber richtig arbeiten?

Vielen Dank!

Aktualisieren

Also der User matyrantwortete mit einem Link zu dem Commit, in dem dieses Verhalten eingeführt wurde, aber es erklärt nicht ganz, was hier passiert, also werde ich versuchen, dies ein wenig zu erklären, falls sich jemand fragt, warum dies so funktioniert.

Das Hauptproblem ist dieses böse "Feature", das von JavaScript geerbt wurde und mit dem wir eine Konstruktorfunktion definieren können, die ein anderes Objekt als das zu erstellende zurückgibt:

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

Und es gibt auch die Tatsache, dass einige einheimische Konstrukteure mögenError, Array, String und womit nicht gerufen werden mussnew: Sie geben nur dann ein neues Objekt des entsprechenden Typs zurück, wenn Sie es vergessen haben.

Am Ende addieren Sie diese beiden hässlichen Dinge und das Ergebnis ist, dass Sie daran denken sollten, zu schreibenclass MyError extends Error then constructor: -> super statt der intuitiverenclass MyError extends Error wenn du das willstinstanceof Betreiber, um richtig mit zu arbeitenMyError. Das liegt daran, dass der implizite Konstruktor von CoffeeScript nur das zurückgibt, was der übergeordnete Konstruktor zurückgibt, und in diesem Fall auchreturn Error.apply(this, arguments) das wird nur ein shinny neues Fehlerobjekt anstelle des Objekts zurückgeben, das Sie als das übergebenethis Streit. Yay!

Update 2 (25. Februar 2013)

Dieses Problemwurde in CoffeeScript 1.5.0 behoben! = D

Das Erweitern nativer Objekte funktioniert nun wie erwartet:

class MyError extends Error
new MyError instanceof MyError # -> true :)
Update 3 (4. März 2013)

Aaund es ist auf 1.6.0 = P gegangen

Antworten auf die Frage(1)

Ihre Antwort auf die Frage