本地Javascript作用域问题

8
如果我这样做:
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问题。

这是为什么呢?


我不确定为什么会这样,但我尝试使用 var a = window.a,它的行为是适当的。 - Ibu
@Ibu 嗯,这很奇怪... - Naftali
因为所有的全局变量都在 window 作用域中。 - jagm
4个回答

12

var a = a;实际上是var a; a = a;,这是由于变量提升造成的。这意味着在赋值时,旧的a已经被新的a遮盖了(它是undefined)。

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

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

如果a是全局变量,你也可以使用var a = window.a;,就像woz建议的那样 - 但由于全局变量通常是个坏主意,最好还是使用参数。


那么我该如何使得我的局部变量和全局变量在局部函数作用域的开始时相等呢?我需要使用一个临时变量吗? - Naftali
1
请看我的编辑。你不能使用临时变量,因为无论你做什么,一旦在函数中有var a,外部的a就不再可访问了。 - ThiefMaster
哦,我忘记了参数 :-P 傻瓜。+1 - Naftali

6

你的函数表达式内部的变量a覆盖了外部作用域声明的a变量。

它变成了NaN,因为在以下赋值中:

var a = a;

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

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

由于它是相同的变量,它保持 undefined 值,当您尝试将任何数字添加到此值时,它变成 NaN

console.log(undefined + 0);

2
在JavaScript中,当前执行上下文(包括变量作用域等)是在代码开始执行之前建立的。
对你来说,这意味着你的本地变量名首先被分配。由于提升,var语句中的标签在当前执行上下文中被初始化为undefined,而这些语句可以出现在函数中的任何位置。(函数语句也在此步骤中初始化。)
接下来,你的代码实际开始执行。在当前执行上下文中,标签a已经被保留,因此var a = a;只是将本地的a(即undefined)赋给它本身。 var a = window.a之所以有效,是因为通过直接访问全局作用域来规避了作用域问题。然而,在非浏览器环境(如Node)中,这种方法不起作用,因为没有window;Node中的全局对象是global

0
在JavaScript中有变量提升,因此您的代码在执行时看起来像这样:
(function () {
    var a;
    a = a; //want to make local a = global a
    ++a;
    console.log("fn",a);
})();

首先,你有一个未定义的本地变量a,然后你将未定义的值赋给变量a。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接