Переменная JavaScript undefined vs not defined

У меня есть HTML-страница со следующим приложением JavaScript.

alert(box);
box = "Thinking outside the box";

В консоли я получаю сообщение "Uncaught ReferenceError: box не определено"

когда я меняю его на:

alert(box);
var box = "Thinking outside the box";

Звонок вызывается и показывает undefined. Я должен уметь это объяснить, у меня есть смутное представление о том, почему это происходит. Я знаю, что, когда я использую var, JavaScript знает, что переменная существует до того, как будет выполнено предупреждение, но необязательно присвоить ей значение? Неужели я здесь? Нужна помощь в понимании этого.

Ответ 1

Когда вы определяете переменную с var, объявление переменной "поднимается" вверху области и, следовательно, переменная определяется для всей области. Инициализация переменной (присвоение ее начального значения) остается в том же месте в коде.

Итак, во втором примере, когда вы делаете alert(box), переменная box уже объявлена ​​из-за инструкции hoisted var. Второй пример:

alert(box);
var box = "Thinking outside the box";

в основном эквивалентен этому (объявление переменной box поднимается вверху области):

var box;
alert(box);
box = "Thinking outside the box";

Это делает переменную box объявленной (хотя и не инициализированной) перед вашим оператором alert(box) и, следовательно, вы получаете результат, который согласуется с объявляемой переменной, но еще не имеет значения (отчеты alert() undefined что происходит, когда переменная существует, но еще не инициализирована).

В вашем первом примере не используется var, и, таким образом, нет никакого подъема, так что в точке, где вы выполняете alert(box), вообще нет переменной с именем box, и вы получаете uncaught reference error.

На SO есть много, много сообщений, которые описывают детали подъема. Вы можете увидеть длинный список из них здесь: https://stackoverflow.com/search?q=javascript+variable+hoisting, где вы найдете дополнительные пояснения о подъеме переменных.

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

Ответ 2

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

Когда вы выполните следующее:

alert(box)
var box = "Thinking outside the box"

Это неявно понимается как:

var box;
alert(box);
box = "Thinking outside the box"

В вашем первом случае у вас нет объявлений переменных, и, следовательно, они не подняты, в этом поле точки undefined

Почему это происходит?

Как Стоян Стефанов объясняет в своей книге "Шаблоны JavaScript", подъем является результатом реализации интерпретатора JavaScript:

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

- Стоян Стефанов, "Шаблоны JavaScript"

Как прочитала сторона, связав эту статью от Safe Shepherd.