Подклассы нативных объектов: instanceof не работает должным образом

Я пытаюсь создать подкласс нативного JSError объект в CoffeeScript, чтобы получить специализированные типы ошибок, но я обнаружил, что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 функции конструктора определены. Когда яdon't определить конструктор в CoffeeScript:

SimpleError = (function(_super) {

  __extends(SimpleError, _super);

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

  return SimpleError;

})(Error);

И когда яdo определить конструктор в 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 оператор правильно работает?

Спасибо!

Update

Так что пользователь Матырответил со ссылкой на коммит, где это поведение было введено, но оно не вполне объясняет, что здесь происходит, поэтому я попытаюсь объяснить это немного на тот случай, если кто-нибудь еще удивится, почему это работает таким образом.

Основной проблемой является эта унаследованная неприятная «особенность» из JavaScript, который позволяет нам определить функцию конструктора, которая возвращает объект, отличный от создаваемого:

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

И есть еще тот факт, что некоторые нативные конструкторы, такие какError, Array, String и тому, что не нужно вызывать сnew: они просто вернут новый объект соответствующего типа, если вы забудете его.

В конце сложите эти две уродливые вещи вместе, и в результате вы должны будете написатьclass MyError extends Error then constructor: -> super вместо более интуитивногоclass MyError extends Error если вы хотитеinstanceof оператор правильно работать сMyError, Это потому, что неявный конструктор CoffeeScript просто возвратит все, что возвращает родительский конструктор, и в этом случаеreturn Error.apply(this, arguments) который будет просто возвращать новый ошибочный объект вместо объекта, который вы передали какthis аргумент. Ура!

Update 2 (Feb 25 2013)

Эта проблемабыло исправлено в CoffeeScript 1.5.0! = D

Теперь расширение нативных объектов работает как положено:

class MyError extends Error
new MyError instanceof MyError # -> true :)
Update 3 (Mar 04 2013)

А он ушел на 1.6.0 = P

Ответы на вопрос(1)

Ваш ответ на вопрос