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 ответа

vars не заблокированы, поэтому последняя строка эквивалентна

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.

Для пояснения я бы порекомендовал вам использовать отладчик, присутствующий в инструментах браузера. Отладьте каждую строку и поймите, как работает область. Надеюсь, поможет.

Другие вопросы по тегам