如果我这样做:
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 = a;
实际上是var a; a = a;
。这意味着在分配时,旧的a
已经被新的undefined
遮蔽。
避免此类问题的最简单方法是将值作为参数传递:
(function (a) {
++a;
console.log("fn",a);
})(a);
如果a
是全局变量,您也可以像woz建议的那样使用var a = window.a;
,但由于拥有全局变量通常是个坏主意,因此最好使用参数。
函数表达式中的a
变量遮蔽了外部作用域上声明的a
变量。
它变为NaN
,因为在分配中:
var a = a;
右侧的a
实际上是指本地范围内的a
。
变量声明是在函数实际开始执行之前完成的,这通常被称为"提升"。
由于它是同一个变量,所以它保持undefined
值,当您尝试将任何数字添加到该值时,它将变为NaN
:
console.log(undefined + 0);
在JavaScript中,当前执行上下文(包括变量范围等内容)是在代码开始执行之前建立的。
这对您来说意味着首先分配您的局部变量名。由于提升,函数中任何位置的var
语句中的标签在当前执行上下文中被初始化为未定义。(函数语句也在此步骤中初始化。)
接下来,您的代码实际上开始执行。a
标签已经在当前执行上下文中保留,因此var a = a;
只是将本地a
(未定义)分配给它自己。
var a = window.a
之所以有效,是因为您可以通过直接访问全局作用域来回避作用域问题。然而,这在非浏览器环境(如Node)中不起作用,因为没有window
;Node中的全局对象是CCD_ 23。
javascript中有一个变量提升,因此执行过程中的代码如下所示:
(function () {
var a;
a = a; //want to make local a = global a
++a;
console.log("fn",a);
})();
因此,首先将局部变量a设为未定义变量,然后将未定义变量分配给变量a