Это явление известно как: Подъем переменной 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 .
Прочтите его.Это даст вам полную картину в деталях.