Подтвердить что ты не робот

Почему классы ES6 не подняты?

Поскольку классы ES6 - это всего лишь синтаксический сахар по сравнению с существующим на основе прототипов на основе JavaScript [1], он (IMO) имеет смысл поднять его определение:

var foo = new Foo(1, 2); //this works

function Foo(x, y) {
   this.x = x;
   this.y = y;
}

Но следующее не будет работать:

var foo = new Foo(1, 2); //ReferenceError

class Foo {
   constructor(x, y) {
      this.x = x;
      this.y = y;
   }
}

Почему классы ES6 не подняты?

4b9b3361

Ответ 1

Почему классы ES6 не подняты?

На самом деле они поднимаются (привязка переменных доступна во всей области), так же как let и const - - они не инициализируются.

Было бы целесообразно поднять его определение

Нет. Никогда не рекомендуется использовать класс перед его определением. Рассмотрим пример

var foo = new Bar(); // this appears to work
console.log(foo.x)   // but doesn't

function Bar(x) {
    this.x = x || Bar.defaultX;
}
Bar.defaultX = 0;

и сравните его с

var foo = new Bar(); // ReferenceError
console.log(foo.x);

class Bar {
    constructor (x = Bar.defaultX) {
        this.x = x;
    }
}
Bar.defaultX = 0;

который выдает ошибку, как и следовало ожидать. Это проблема для статических свойств, прототипов mixins, декораторов и всего остального. Кроме того, это очень важно для подкласса, который полностью сломался в ES5, когда вы использовали класс с его не скорректированным прототипом, но теперь выдает ошибку, если класс extend ed еще не инициализирован.

Ответ 2

В Javascript все объявления (var, let, const, function, function *, class) подняты, но должны быть объявлены в той же области.

Как вы сказали, "классы ES6 - это просто синтаксический сахар над существующим наследованием на основе прототипов JavaScript"

Итак, давайте понять, что это такое?

Здесь вы объявили класс, который на самом деле является "специальной функцией". Предположим, что ваша функция Foo() и класс Foo оба находятся в глобальной области.

class Foo {
   constructor(x, y) {
      this.x = x;
      this.y = y;
   }
}

Ниже приведен скомпилированный код вашего класса Foo.

var Foo = (function () {
    function Foo(x, y) {
        this.x = x;
        this.y = y;
    }
    return Foo;
}());

Внутренне ваш класс преобразуется в функцию с тем же именем внутри функции обертки (iife), и эта функция-обертка возвращает вашу функцию.

Поскольку область действия вашей функции (класса) изменена. и вы пытаетесь создать объект функции в глобальном масштабе, который на самом деле не существует.

вы получаете функцию в переменной Foo, когда компиляция приходит к ней. поэтому позже у вас есть функция в var, вы можете создать объект этого.

Ответ 3

Хотя невключенные классы (в том смысле, что они ведут себя как привязки let) можно считать предпочтительными, так как они ведут к более безопасному использованию (см. Ответ Берги), приведенное ниже объяснение, найденное в блоге 2ality, кажется, предоставляет чуть более фундаментальную причину для эта реализация:

Причина этого ограничения [non-hoisting] заключается в том, что классы могут иметь предложение extends, значение которого является произвольным выражением. Это выражение должно быть оценено в правильном "месте", его оценка не может быть поднята.