Javascript область видимости переменных
Выходное значение равно 15 (в f, x принимается равным 10, а y равно 7) со следующим:
var x = 5;
function f(y) { return (x + y) - 2};
function g(h) { var x = 7; return h(x) };
{ var x = 10; z = g(f); console.log(z) };
Почему x взял значение из 4-й строки, а не из 1-й строки (и почему не из 3-й строки)?
3 ответа
var
s не заблокированы, поэтому последняя строка эквивалентна
x = 10; z = g(f); console.log(z)
Теперь должно быть понятнее, что значение x
был изменен на 10
до f
был выполнен.
Также важно отметить, что свободные переменные оцениваются при вызове функции, а не при ее определении. И, конечно, значение переменной может меняться между определением функции и вызовом функции, как в вашем примере.
В третьей строке x
является локальным для g
и, следовательно, полностью независим от "внешней" переменной x
,
Смотрите также Какова область видимости переменных в JavaScript?
Гораздо более простой пример, демонстрирующий это поведение:
var x = 5;
function foo() {
console.log(x);
}
x = 10;
foo(); // outputs 10
var x = 5;
function f(y) { return (x + y) - 2};
function g(h) { var x = 7; return h(x) };
{ var x = 10; z = g(f); console.log(z) };
это немного беспорядок, так что давайте исправим это:
/* 1 */var x = 5;
/* 2 */
/* 3 */function f(y) {
/* 4 */ return (x + y) - 2
/* 5 */};
/* 6 */
/* 7 */function g(h) {
/* 8 */ var x = 7;
/* 9 */ return h(x)
/* 10 */};
/* 11 */
/* 12 */{
/* 13 */ var x = 10;
/* 14 */ z = g(f);
/* 15 */ console.log(z)
/* 16 */};
Это все еще имеет ряд проблем, которые я дословно скопировал. Все, что я сделал, это добавил пробел. Теперь я собираюсь очистить код, чтобы он отражал фактический порядок выполнения.
// variable and function declaration happens before assignment
// variables are scoped to their containing function,
// or, when no parent function exists, to global scope
var x;
function f(y) {
// cleaned up semicolon usage (lines 4 & 5)
// while JavaScript's automatic semicolon insertion would work
// it's generally better to be explicit about intent
return x + y - 2;
}
function g(h) {
// again separated variable declaration from assignment
// from line 8 above
var x;
x = 7;
return h(x);
}
// removed unnecessary block scope from lines 12 & 16
// variable assignment now can happen after declaration
// x is assigned from line 1 above
x = 5;
// x is subsequently overwritten from line 13 above as
// JS variables don't have block scope
// duplicate var declaration has no effect and is removed
x = 10;
z = g(f);
console.log(z);
Теперь, когда код правильно отформатирован, сразу становится ясно, что x
будет иметь значение 10
потому что порядок выполнения приводит к x
перезаписывается
В javaScript нет ничего, что называется областью уровня блока. Он обрабатывается так же, как глобальная переменная. Теперь давайте проанализируем эти утверждения и их объем. Изначально вы объявили var x = 5;, Затем вы определили две функции, а затем снова определили var x = 10;, Обратите внимание, что JavaScript переопределит значение x. Теперь х равен 10 во всем мире.
Теперь вы объявили z = g(f); Вы передаете функцию в качестве параметра. Внутри g вы снова объявили x как var x = 7;, Обратите внимание, что переменная, определенная внутри функции, имеет более высокий приоритет, чем то же имя переменной, объявленное в глобальной области видимости, а также текущее значение переменной отображается только для этой функции. За пределами g все знают, что x равен 10. Но внутри g значение x будет равно 7.
Теперь вы вернулись h(x); это означает, что вы называете f(y) как f(7); f по-прежнему знает, что x равен 10, и не знает, существовал ли он даже внутри функции g. Таким образом, f вычисляет (10 + 7) - 2. Следовательно, значение z становится 15.
Для пояснения я бы порекомендовал вам использовать отладчик, присутствующий в инструментах браузера. Отладьте каждую строку и поймите, как работает область. Надеюсь, поможет.