Разве версии 1 и 2 исходного кода на самом деле не совпадают? (все классы расширяют Object).
Нет, не вполне . Давайте сравним:
class Base {
}
и
class Sub extends Object {
}
Это правда, что и Base.prototype
, и Sub.prototype
используют Object.prototype
в качестве прототипов, но это не делает их одинаковыми , Два отличия:
Base
(функция конструктора) использует Object
в качестве прототипа; Sub
использует Function.prototype
. Base
будет создавать объект, когда вы вызываете его через new
; Sub
не будет, он ожидает, что конструктор суперкласса (Object
) сделает это. Что означает, что это должно называть это. (Конструкторы отмечены, чтобы указать, являются ли они конструкторами базовых или подклассов, и обработка оператора new
действует в соответствии с.)
Демонстрация # 1 (с механизмом ES2015 + JavaScript) :
class Base {
}
class Sub extends Object {
}
// Both `prototype` properties inherit from `Object.prototype`
console.log(Object.getPrototypeOf(Base.prototype) === Object.prototype);
console.log(Object.getPrototypeOf(Sub.prototype) === Object.prototype);
// But the constructors themselves inherit from different things
console.log(Object.getPrototypeOf(Base) === Function.prototype);
console.log(Object.getPrototypeOf(Sub) === Object);
И поэтому, если версия 1 не вызывает super()
, похоже, что конструктор Object
ничего не делает, поэтому версия 2 также нет причин называть это?
Он должен это называть. Это не скомпилируется в нативном JavaScript (ES2015 +):
class Example extends Object {
constructor() {
this.foo = "bar";
}
}
console.log(new Example().foo);
Если у вас есть extends
, вы должны вызвать super
, чтобы создать новый объект.
My Sub
вверху ответа компилируется, потому что у него нет явного конструктора, поэтому он получает конструктор подкласса по умолчанию (constructor(...args) { super(...args); }
). Но Example
терпит неудачу, потому что он имеет явный конструктор, но не делает вызов super
.