Podklasowanie obiektów rodzimych: instancja nie działa poprawnie

Próbuję podklasować rodzimy JSError obiekt w CoffeeScript, aby uzyskać wyspecjalizowane typy błędów, ale odkryłem, żeinstanceof nie działa poprawnie, jeśli nie zdefiniuję konstruktora w podklasach:

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

Problem wydaje się być spowodowany przez sposóbwygenerowany JS zdefiniowano funkcje konstruktora. Kiedy janie zdefiniuj konstruktor w CoffeeScript:

SimpleError = (function(_super) {

  __extends(SimpleError, _super);

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

  return SimpleError;

})(Error);

A kiedyrobić zdefiniuj konstruktor w CoffeeScript:

SuperConstructorError = (function(_super) {

  __extends(SuperConstructorError, _super);

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

  return SuperConstructorError;

})(Error);

Jak widać, różnica jest prostareturn w pierwszym przypadku. Nie rozumiem, dlaczego to robi różnicęinstanceof jednak zachowanie, ponieważ super konstruktor jest właśnie stosowany dothis obiekt (tj. super konstruktor nie jest wywoływanynew), ale znowu nie rozumiem, jak działają konstruktory JS = P

Dziwne jest to, że to zachowanie zdaje się mieć miejsce tylko podczas podklasy rodzimych obiektów JS. Jeśli podklasuję klasy CoffeeScript, wszystko działa zgodnie z oczekiwaniami.

Każdy pomysł, dlaczego tak się dzieje i jak mogę uniknąć pisania fałszywych konstruktorów tylko dlainstanceof operator działa poprawnie?

Dzięki!

Aktualizacja

Więc matyr użytkownikaodpowiedział z linkiem do zatwierdzenia, w którym to zachowanie zostało wprowadzone, ale nie wyjaśnia to, co się tutaj dzieje, więc spróbuję wyjaśnić to trochę na wypadek, gdyby ktoś inny zastanawiał się, dlaczego to działa w ten sposób.

Głównym problemem jest odziedziczona nieprzyjemna „cecha” JavaScript, która pozwala nam zdefiniować funkcję konstruktora, która zwraca obiekt inny niż budowany:

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

Jest też fakt, że niektórzy konstruktorzy natywniError, Array, String i nie trzeba z tym dzwonićnew: po prostu zwrócą nowy obiekt odpowiedniego typu, jeśli zdarzy ci się go zapomnieć.

W końcu dodaj te dwie brzydkie rzeczy razem, w wyniku czego powinieneś pamiętać o pisaniuclass MyError extends Error then constructor: -> super zamiast bardziej intuicyjnegoclass MyError extends Error jeśli chceszinstanceof operator działa poprawnieMyError. Dzieje się tak, ponieważ domyślny konstruktor CoffeeScript po prostu zwróci to, co zwraca konstruktor nadrzędny, iw tym przypadku to zrobireturn Error.apply(this, arguments) który zwróci po prostu nowy obiekt błędu zamiast obiektu, który przekazałeś jakothis argument. Tak!

Aktualizacja 2 (25 lutego 2013 r.)

Ten problemzostał naprawiony w CoffeeScript 1.5.0! = D

Teraz rozszerzanie obiektów rodzimych działa zgodnie z oczekiwaniami:

class MyError extends Error
new MyError instanceof MyError # -> true :)
Aktualizacja 3 (04 marca 2013 r.)

Aa i zniknęło 1.6.0 = P

questionAnswers(1)

yourAnswerToTheQuestion