Локальная проблема области видимости Javascript

если я сделаю это:

var a = 0;

(function () {
    var a = a; //want to make local a = global a
    ++a;
    console.log("fn",a);
})();

console.log(a);​

выход:

fn NaN
0

почему a внутри самоисполняющейся функции стать NaN?

Я знаю, что это работает нормально, если я делаю:

(function () {
    var b = a;
    ++b;
    console.log("fn",b); // fn 1
})();

но если я пойду по пути первой версии, у нее есть NaN вопрос.

почему это происходит?

4 ответов


var a = a; на самом деле var a; a = a; из-за переменной поднимая. Это означает, что на момент назначения старый a уже затенен новым (который является undefined).

самый простой способ избежать подобных проблем-передать значение в качестве параметра:

(function (a) {
    ++a;
    console.log("fn",a);
})(a);

в случае a является глобальной переменной, которую вы также можете использовать var a = window.a; как Возняк предложил - но поскольку глобальные переменные обычно являются плохой идеей, лучше оставаться с параметры.


на a переменной внутри выражения функции тени the a переменная, объявленная во внешней области.

становится NaN, так как в задании:

var a = a;

правой a это на самом деле имею в виду a в локальной области.

объявления переменных выполняются до того, как функция фактически начнет выполняться, это обычно известно как "подъем".

так как это то же самое переменная, она содержит undefined значение, и когда вы пытаетесь добавить любое число к этому значению, оно становится NaN:

console.log(undefined + 0);

в JavaScript текущий контекст исполнения (который включает в себя такие вещи, как переменная область) устанавливается до начинается выполнение кода.

для вас это означает, что сначала выделяются имена локальных переменных. Из-за поднимать, метки var заявления в любом месте функции инициализируются undefined в текущем контексте исполнения. (инструкции функции также инициализируются на этом шаге.)

далее, ваш код фактически начинает выполняться. The a метка уже зарезервирована в текущем контексте выполнения, поэтому var a = a; просто назначает local a (т. е. undefined) к себе.

var a = window.a работает, потому что вы обходите проблему области, напрямую обращаясь к глобальной области. Однако это не работает в средах без браузера (например, Node), потому что нет window; глобальный объект в узле global.


в javascript есть переменная, поэтому ваш код во время выполнения выглядит так:

(function () {
    var a;
    a = a; //want to make local a = global a
    ++a;
    console.log("fn",a);
})();

Итак, сначала у вас есть локальная переменная a как неопределенная, а затем вы назначаете неопределенную переменной a