2016-05-25 4 views
-1

Выход 15 (в е, х берутся 10 и у 7) следующий:Javascript область видимости переменных

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) }; 

Почему х принимает значение от 4-я строки, а не от 1-я строка (и почему не 3-я строка)?

ответ

5

var ы являются не блокировал область видимости, так что последняя строка эквивалентна

x = 10; z = g(f); console.log(z) 

Это должно быть ясно теперь, что значение x было изменено на 10перед темf был выполнен.
Также важно отметить, что свободные переменные оцениваются, когда функция называется, а не тогда, когда она была определена. И, конечно, значение переменной может меняться между определением функции и вызовом функции, как и в вашем примере.

В третьей строке x является локальным для g и поэтому полностью не зависит от «внешней» переменной x.

Смотрите также What is the scope of variables in JavaScript?


гораздо более простой пример, демонстрирующий это поведение было бы:

var x = 5; 
function foo() { 
    console.log(x); 
} 
x = 10; 
foo(); // outputs 10 
3
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 перезаписи.

+0

Я был очень взволнован, когда читал, что вы все глубже и глубже. Я действительно надеялся, что ты еще глубже. – IMTheNachoMan

+0

@IMTheNachoMan, поскольку вопрос был о том, почему 'x' имел особое значение, я остановился на этом этапе. Если вопрос был «почему« z »имеет значение, которое он делает?» Я бы прошел через всю казнь. Это просто вопрос соблюдения программы. – zzzzBov

+0

Я знаю. Я пошутил. Мне просто понравилось, как вы это делали шаг за шагом. :) – IMTheNachoMan

0

В javaScript ничто не называется областью уровня блока. Он обрабатывается так же, как и глобальная переменная. Теперь давайте проанализируем эти утверждения и их объем. Сначала вы объявили var x = 5;. Затем вы определили две функции, а затем снова определили var x = 10;. Обратите внимание, что JavaScript переопределит значение x. Теперь 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.

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

Смежные вопросы