Правда ли, что Babel действительно не нужно вызывать super (), если класс расширяет Object? - PullRequest
4 голосов
/ 31 января 2020

Я заметил с использованием Babel , если я перевожу

class Rectangle {
  a = 1;
}

с использованием stage-0, тогда результирующий код имеет функцию конструктора, но нет вызова super()

Но если код изменяется на:

class Rectangle extends Object {
  a = 1;
}

, то передаваемый код будет:

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

class Rectangle extends Object {
  constructor(...args) {
    super(...args);

    _defineProperty(this, "a", 1);
  }

}

Разве версии 1 и 2 исходного кода на самом деле не совпадают ? (все классы расширяют Object). И поэтому, если версия 1 не вызывает super(), похоже, что конструктор Object ничего не делает, поэтому у версии 2 также нет причин вызывать его?

1 Ответ

5 голосов
/ 31 января 2020

Разве версии 1 и 2 исходного кода на самом деле не совпадают? (все классы расширяют Object).

Нет, не вполне . Давайте сравним:

class Base {
}

и

class Sub extends Object {
}

Это правда, что и Base.prototype, и Sub.prototype используют Object.prototype в качестве прототипов, но это не делает их одинаковыми , Два отличия:

  1. Base (функция конструктора) использует Object в качестве прототипа; Sub использует Function.prototype.
  2. 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.

...