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

Переменная не может быть объявлена ​​или изменена

У меня вопрос о JavaScript. Когда я объявляю новую переменную и назначаю ей новый экземпляр класса, если ошибка выбрана, переменная становится полностью непригодной.

Код ниже должен вызывать ошибку

class MyClass {


    constructor (config) {

        this.someProperty = config.someProperty || '';

    }


}

let myClassInstance = new MyClass();

Если я попытаюсь присвоить ему что-то, JavaScript будет вызывать ошибку.

myClassInstance = '123'

Uncaught ReferenceError: myClassInstance не определен

Затем я попытался определить переменную

let myClassInstance = '123'

Uncaught SyntaxError: идентификатор 'myClassInstance' уже объявлен

Переменная также не может быть удалена. Есть ли что-то, что мы можем сделать с этой проблемой? Мне просто интересно, конечно, я обработаю передачу undefined как конфигурацию для конструктора.

EDIT: Я также попытался использовать var, я могу повторно использовать myClassInstance. Интересно, почему, если я использую, пусть эта переменная не может быть удалена, декларативное или новое значение не может быть переназначено.

EDIT 2: Я могу обрабатывать передачу undefined или передавать пустой объект. Просто чистое любопытство, что происходит в консоли JS с этой переменной, также код не будет выполняться, если вы вставляете все сразу

4b9b3361

Ответ 1

Запуск кода в интерактивной консоли создает надуманную ситуацию, которая не может произойти при типичном выполнении кода.

Во-первых, то, что вы видите, не относится к ошибкам, возникающим в конструкторах классов. Вы можете наблюдать такое же поведение, если вы выполняете оператор let, где RHS выдает ошибку:

let myVariable = "".boom();

Документация в MDN говорит о "временной мертвой зоне", где существует переменная, объявленная с помощью let, но рассматривается как не существующая пока оператор let не будет успешно выполнен.

Из спецификации ES6:

Переменные создаются, когда их содержащая Лексическая среда создается, но может быть недоступна каким-либо образом, пока не будут оценены переменные LexicalBinding.

Простыми словами, переменная была создана, но недоступна, поскольку ее "Лексическая привязка" не была оценена.

Используя консоль, вы создали ситуацию, в которой:

  • Оператор let не был успешно выполнен (так что ReferenceError пытается получить доступ к своей переменной).
  • У вас есть два let для одного и того же имени переменной в пределах одной области (поэтому вторая создает синтаксическую ошибку). (nb Просто наличие двух let в том же объеме приведет к сбою кода на этапе компиляции, прежде чем первый из них даже попытается выполнить, если вы не вводили код немного за раз в консоль).

Это ситуация, которая не может произойти в обычном коде.

Как правило, вы не сможете продолжать выполнение операторов в области, где была вызвана ошибка, поэтому первая пуля была бы невозможна. Консоль позволяет это сделать.

В обычных обстоятельствах это было бы невозможно, потому что код завершился неудачно на этапе компиляции, прежде чем первый оператор let мог даже попытаться запустить.

Итак, почему вы получаете ошибку в обоих случаях.

Ответ 2

Хорошо, этот вопрос действительно интересен, и я, возможно, нашел для него ответ.

Явление, которое вы описываете, скорее всего связано с тем, как механизм Javascript компилирует ваш код. Хотя программисту может показаться иначе, компиляция состоит из нескольких этапов и выполняется на разных этапах процесса. Таким образом, в зависимости от того, какая у вас ошибка в коде, этот процесс может завершиться в любой момент процесса.

Итак, если ваше создание объекта ошибочно (config is undefined), но синтаксис сам по себе является прекрасным (с точки зрения языка), вы получите ошибку позже в процессе компиляции по сравнению с чем-то, что незаконно в Javascript вообще.

См., let довольно сложный, поскольку он предотвращает столкновение имен имен (следовательно, ошибка Indentifier 'myClassInstance' has already been defined). Это не похоже на var, у которого нет этой функции.

Из Документация MDN:

Повторное использование одной и той же переменной в той же функции или области блока вызывает синтаксический эффект.

if (x) {
  let foo;
  let foo; // SyntaxError thrown.
}

В ECMAScript 2015 давайте поднимите переменную до вершины блок. Однако, ссылаясь на переменную в блоке до объявление переменной приводит к использованию ReferenceError. Переменная находится в "временная мертвая зона" от начала блока до объявления обрабатывается.


TL; DR

Следующий код вызовет ошибку ранее во время процесса компиляции

let myClassInstance = new MyClass();
let myClassInstance = '123';

по сравнению с:

let myClassInstance = new MyClass();
myClassInstance = '123';

Это потому, что первый является незаконным синтаксисом в Javascript, а второй - нет. В последнем случае код будет компилироваться отлично, но не будет работать во время выполнения, потому что аргумент undefined.


EDIT:

Я нашел этот блог и довольно интересный текст. Отрывок:

А? Проще говоря, этот механизм JavaScript принимает ваш исходный код, разбивает его на строки (a.k.a. lexes it), берет эти строки и преобразует их в байт-код, который компилятор может понять, а затем выполняет его.

Другой учебник по глубокому погружению здесь.