Chrome console уже объявленные переменные вызывают неопределенные ссылочные ошибки для let

недавно я столкнулся с этой странной вещью в консоли chrome. Здесь я намеренно назначаю неопределенную вещь a, чтобы выбросить ошибку.

let a = werwr // Uncaught ReferenceError: werwr is not defined

затем, когда я попытался назначить что-то законное a, это произошло:

let a = "legit string"   // Uncaught SyntaxError: Identifier 'a' has already been declared

поэтому я не могу использовать "let", потому что a уже объявлен. Поэтому я попытался переназначить что-то еще на "уже объявленное"

a = "legit string"   //  Uncaught ReferenceError: a is not defined

поэтому кажется, что я не могу переназначить что-то еще, но в то же время время, a было объявлено, поэтому я не могу использовать let снова.

Я понимаю разницу между объявлением и назначение переменной. Однако здесь кажется, что не может быть сделано снова. Имеет ли это какое-то отношение к области "let" в консоли? Потому что то же самое полностью работает на "ВАР"

var a = werwr 
// Uncaught ReferenceError: werwr is not defined

a = ”legit string“  
// ”legit string“

var a = "legit string" 
// Uncaught SyntaxError: Identifier 'a' has already been declared

следовать-вверх

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

throw new Error
let example = 5
// same errors as before

пока в этом случае пример можно переназначить снова.

let example
throw new Error
example = 5

2 ответов


это происходит, когда вы вводите временную мертвую зону на глобальном уровне. Как вы знаете, let декларации поднимаются, но остаются неинициализированными. Из-за потока управления может случиться так, что переменная никогда не инициализируется:

function …() {
    if (false)
        example; // would throw a ReferenceError if it was evaluated
    … // do something
    if (true)
        return; // stop!
    let example = 5; // never executed
}

Это нормально, в области функции. Возможно, что - то пошло не так, возможно, переменная вообще не нужна-в следующем вызове будет создана новая область с новой переменной.

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

throw new Error;
let example = 5;

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

этой обсуждался на es-discuss, но считается неуместным. Если верхний уровень <script> выполнение выдает ошибку, у вас есть большие проблемы, чем неинициализированные переменные. Нет пути для восстановления. Если вам нужен один (например, пытаясь повторно объявить его в последовательных сценариях), вы должны использовать var в любом случае.

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


вы должны знать о подъеме в JS. В основном, декларации, как это let a = werwr;

интерпретируется как let a; a = werwr;

и поэтому a уже объявлен при запуске второй строки кода.

обновление

Итак, в спецификациях ES есть примечание https://tc39.github.io/ecma262/#prod-LetOrConst

объявления let и const определяют переменные, которые относятся к области бегущий лексическое окружение контекста исполнения. Переменные создается, когда создается их содержащая лексическая среда но не может быть доступен каким-либо образом, пока LexicalBinding переменной оценено. Переменная, определенная LexicalBinding с инициализатором присваивается значение AssignmentExpression инициализатора, когда LexicalBinding вычисляется, а не при создании переменной. Если LexicalBinding в объявлении let не имеет Инициализатор переменной присваивается значение undefined при LexicalBinding оценивается.

...

"но не могут быть доступны каким-либо образом, пока не будет оценено LexicalBinding переменной" это означает, что объявление должно быть успешно завершено, прежде чем вы сможете получить доступ к переменной (получение значения, присвоение значения или выполнение typeof или delete);

в вашем случае LexicalBinding переменной interupted исключение.

let a = werwr // Uncaught ReferenceError: werwr is not defined

пожалуйста, перейдите по ссылке и узнайте больше об этом. Если вы найдете способ восстановить varaible a, пожалуйста, скажите мне. Спасибо, сегодня я узнал что-то новое о JavaScript.