如果我这样做:
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
问题。
为什么会这样?
答案 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