本地Javascript范围问题

时间:2012-07-12 17:28:05

标签: javascript scope

如果我这样做:

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 个答案:

答案 0 :(得分:12)

由于变量提升,

var a = a;实际上是var a; a = a;。这意味着在分配时,旧a已经被新的undefined遮蔽了。{/ 1}。

避免这类问题的最简单方法是将值作为参数传递:

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

如果a是一个全局变量,你也可以像woz suggested那样使用var a = window.a; - 但是因为拥有全局变量通常是一个坏主意,所以更好地保留参数。

答案 1 :(得分:6)

函数表达式中的a变量 shadow 在外部作用域上声明的a变量。

它变为NaN,因为在作业中:

var a = a;

右侧a实际上是指本地范围内的a

变量声明在函数实际开始执行之前完成,这通常称为“提升”。

由于它是同一个变量,因此它包含undefined值,当您尝试向此值添加任意数字时,它变为NaN

console.log(undefined + 0);

答案 2 :(得分:2)

在JavaScript中,在代码开始执行之前,建立了当前execution context(包括变量作用域等内容)。

这对您意味着首先分配您的本地变量名称。由于提升,函数中任意位置的var语句中的标签在当前执行上下文中初始化为 undefined 。 (函数语句也在此步骤中初始化。)

接下来,您的代码实际上开始执行。 a标签已在当前执行上下文中保留,因此var a = a;只是将本地a未定义)分配给自身。

var a = window.a有效,因为您可以通过直接访问全局范围来回避范围问题。但是,这在非浏览器环境(如Node)中不起作用,因为没有window; Node中的全局对象是global

答案 3 :(得分:0)

javascript中有一个变量提升,因此执行期间的代码如下所示:

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

首先你将局部变量a定义为未定义,然后将undefined赋值给变量a