Это явление известно как: Подъем переменных JavaScript .
Вы никогда не обращаетесь к глобальной переменной в своей функции; вы всегда обращаетесь только к локальной value
переменной.
Ваш код эквивалентен следующему:
var value = 10;
function test() {
var value;
console.log(value);
value = 20;
console.log(value);
}
test();
Вы все еще удивлены undefined
?
Пояснение:
Это то, с чем рано или поздно сталкивается каждый программист JavaScript. Проще говоря, любые объявленные вами переменные всегда поднимаются на вершину вашего локального замыкания. Таким образом, даже если вы объявили свою переменную после первого console.log
вызова, она по-прежнему считается, как если бы вы объявили ее до этого.
Однако поднимается только часть объявления; с другой стороны, назначение - нет.
Итак, при первом вызове console.log(value)
вы ссылались на локально объявленную переменную, которой еще ничего не назначено; следовательно undefined
.
Вот еще пример :
var test = 'start';
function end() {
test = 'end';
var test = 'local';
}
end();
alert(test);
Как вы думаете, что это предупредит? Нет, не просто читай, думай об этом. Какая ценностьtest
?
Если вы сказали что-нибудь кроме start
, вы ошибались. Приведенный выше код эквивалентен этому:
var test = 'start';
function end() {
var test;
test = 'end';
test = 'local';
}
end();
alert(test);
так что глобальная переменная никогда не затрагивается.
Как видите, независимо от того, где вы помещаете объявление переменной, оно всегда поднимается в верхнюю часть вашего локального закрытия.
Примечание:
Это также относится к функциям.
Рассмотрим этот фрагмент кода :
test("Won't work!");
test = function(text) { alert(text); }
что даст вам справочную ошибку:
Uncaught ReferenceError: тест не определен
Это сбивает с толку многих разработчиков, поскольку этот фрагмент кода отлично работает:
test("Works!");
function test(text) { alert(text); }
Причина этого, как указано, в том, что часть назначения не поднимается. Итак, в первом примере при test("Won't work!")
запускеtest
переменная уже была объявлена, но ей еще не назначена функция.
Во втором примере мы не используем присвоение переменных. Скорее всего , мы используем правильный синтаксис объявления функции, которая делает получить функцию полностью водрузили.
Бен Черри написал отличную статью по этому поводу под соответствующим названием JavaScript Scoping and Hoisting .
Прочтите это. Это даст вам полную картину во всех деталях.