Почему JavaScript поднимает переменные?

94

Почему JavaScript поднимает переменные?

Что мотивировало конструкторы, когда они решили реализовать подъемные механизмы? Есть ли другие популярные языки, на которых это можно сделать?

Предоставьте соответствующие ссылки на документацию и / или записи.

Кславдий
источник
7
Я подозреваю, что на данный момент это исторический момент, и я серьезно сомневаюсь, что изначально это было что-то кроме «простоты реализации».
Дэйв Ньютон
4
Честно говоря, спросите Брендана Эйха, он, кажется, довольно отзывчивый.
Феликс Клинг,
22
Как этот вопрос не конструктивно?
Francisc
18
@Francisc добро пожаловать в Stack Overflow, где все, о чем вы можете спросить, - это перемещение a divв jQuery
Xlaudius
20
Это действительно важный вопрос. Это должно было быть разрешено. Это не была приманка. Подъем является одним из основных элементов понимания того, как работает JavaScript, и «почему» - это законный вопрос, который рассматривается в большинстве учебников по этому языку. Это НЕ нормально, что люди, использующие Stack Overflow, ПОСТОЯННО топчутся на такие вопросы людей.
Bearvarine

Ответы:

55

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

Интерпретация JS-кода выполняется в два прохода. Во время первого прохода интерпретатор обрабатывает объявления переменных и функций.

Второй проход - это фактический этап выполнения кода. Интерпретатор обрабатывает функциональные выражения и необъявленные переменные.

Таким образом, мы можем использовать концепцию «подъема» для описания такого поведения.

lxgreen
источник
15
Мне лично очень не нравится слово «подъем». Это дает ложное представление о том, что объявления переменных и функций волшебным образом поднимаются в верхнюю часть текущей области, тогда как на самом деле интерпретатор JS, как вы упомянули, сканирует исходный код на предмет привязок, а затем выполняет код.
contactmatt
Теперь я понял, почему JS наиболее неправильно понимаемый язык, я не видел этого ни в одном учебнике. Так и запутался с подъемом (и потоком интепретатора).
Swapnil Patwa
17
Эээ, это на самом деле не объясняет причины. Однопроходный интерпретатор (который не привел бы к подъему) был бы намного проще - так почему же дизайнеры выбрали два прохода?
Берги
1
Это не объясняет, почему именно переменные поднимаются. Функции имеют смысл, переменные - нет (в большинстве случаев) - я считаю, что это ошибка.
Джош М.
Джош М. Это так подробно описано, я не думаю, что это «ошибка» ... (хотя я согласен, что этот ответ на самом деле не отвечает на рассуждение)
Джонас
10

Создатель JS Брендан Эйх однажды сказал (в Твиттере) :

«Таким образом, подъем var был [] непреднамеренным следствием подъема функции, отсутствия области видимости блока, [и] JS как срочной работы 1995 года».

Он также объяснил, что ...

"функция подъема позволяет выполнять декомпозицию программы сверху вниз, 'let rec' бесплатно, вызовите перед объявлением; var hoisting с тегами."

Брендан Эйх

Есть ли другие популярные языки, на которых это можно сделать?

Я не знаю других популярных языков, которые поднимали бы переменные таким же образом.Я думаю, что даже ActionScript - еще одна реализация ECMAScript, используемая при разработке Flash - не поддерживает подъем. Это стало источником путаницы и разочарования для разработчиков, знакомых с другими языками и изучающих JavaScript.

ОБНОВЛЕНИЕ: из комментариев Python имеет аналогичное поведение при подъеме переменных .

гфуллам
источник
2
Ставить +1, поскольку это единственный ответ, который пытается напрямую ответить на вопрос.
Дэймон
1
Спасибо за этот ответ. Полностью согласен с @Damon!
codingbryan
1
Еще один популярный язык, поддерживающий подъем переменных, - это Python: stackoverflow.com/q/63337235/2326961
Maggyero
2

Это связано с тем, что интерпретатор javascript интерпретирует код за два цикла.

  1. Автозавершение / компиляция кода:
  2. Выполнение кода:

В 1-м цикле все объявления переменных и функций переносятся в верхнюю часть области действия функции, в которой они выполняются. Это помогает в создании variableObjectsдляexecution context of функции еще до ее выполнения.

На 2-м этапе присвоение значений, операторы кода и вызовы функций происходят построчно, как и ожидалось.

Вы можете прочитать немного подробнее здесь.

Это даст вам более полную картину вокруг поведения вокруг let, constи classдеклараций, также приоритете следует между переменными и функциями.

Джасприт Сингх
источник
1
Вы имеете в виду, что это следствие выбора дизайна? Если да, вы должны четко указать это в своем ответе. Но, читая ответ Брендана Эйха, возможно, это была желанная функция, это зависит от того, как вы интерпретируете последнее предложение. Итог, я до сих пор не знаю, почему точно
Бомбинош