Ответ 1
Короче говоря, расширение с использованием кода, переведенного с помощью Babel, работает только для классов, построенных определенным образом, и многие родные вещи не кажутся подобными. Вавилонские документы предупреждают, что расширение многих родных классов не работает должным образом.
Вы можете создать класс буфера, который создает свойства "вручную", что-то вроде этого:
class ErrorClass extends Error {
constructor (message) {
super();
if (Error.hasOwnProperty('captureStackTrace'))
Error.captureStackTrace(this, this.constructor);
else
Object.defineProperty(this, 'stack', {
value: (new Error()).stack
});
Object.defineProperty(this, 'message', {
value: message
});
}
}
Затем продолжите этот класс:
class FooError extends ErrorClass {
constructor(message) {
super(message);
}
}
Почему он не работает так, как вы ожидали?
Если вы посмотрите на то, что перерисовано, вы увидите, что babel сначала назначает копию прототипа суперкласса для подкласса, а затем, когда вы вызываете new SubClass()
, эта функция вызывается:
_get(Object.getPrototypeOf(FooError.prototype), "constructor", this).call(this, message)
Где _get - вспомогательная функция, введенная в script:
(function get(object, property, receiver) {
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent === null) {
return undefined;
} else {
return get(parent, property, receiver);
}
} else if ("value" in desc) {
return desc.value;
} else {
var getter = desc.get;
if (getter === undefined) {
return undefined;
}
return getter.call(receiver);
}
});
он делает что-то вроде поиска дескриптора свойства constructor
прототипа прототипа под-класса и пытался вызвать его получатель с новым экземпляром подкласса в качестве контекста, если он существует или возвращает его значение (if ("value" in desc)
), в этом случае сам конструктор Error. Он не присваивает ничего this
из супервызов, так что, когда новый объект имеет правильный прототип, он не строится так, как вы ожидаете. В основном супер-вызов ничего не делает для вновь созданного объекта, просто создает новый Error
, который ничем не назначен.
Если мы используем описанный выше ErrorClass
, он придерживается структуры классов, как и ожидалось в Babel.