考虑以下两个JavaScript代码段:
var x = 2;
function f() {
var y = x;
eval('var x;');
return y;
}
VS
var x = 2;
function f() {
var y = x;
var x;
return y;
}
唯一的区别是我已将eval('var x;');
替换为var x;
。
第一个返回2
,但第二个返回undefined
。为什么呢?
答案 0 :(得分:4)
解析器将变量声明提升到词法范围的顶部。在第二个代码块中,它实际运行的方式是:
function f() {
var x, y;
y = x;
return y;
}
函数声明也会被提升。实际效果是变量声明应被视为始终包含它出现的整个词法范围。如果在函数中使用x
任何地方声明变量var
,则该函数中对x
的每次引用都是对局部变量。
在你的第一个例子中,eval()
行只是一个正则表达式语句,因此它按照它在函数中出现的顺序执行。
答案 1 :(得分:1)
因为第二个,在执行任何其他语句之前,var
被提升到函数的开头。
所以就好像你的代码就是这样:
var x = 2;
function f() {
var x, y
y = x;
return y;
}
但是对于第一个,var x
是eval()
表达式的一部分,因此它没有机会像第二个那样被提升*。
*“悬挂”一词不是官方用语。它只是人们用来描述声明在执行上下文中评估任何表达式之前发生的事实。函数声明也被悬挂。
答案 2 :(得分:1)
这是因为当解释器处于函数范围内时,它会将值undefined
设置为在其中声明的所有变量(带有var
关键字前缀)。无论你在何处放置声明,如果函数内部有变量声明,变量的值将为undefined
,直到您明确设置它的值为止。在第一种情况下,当eval('var x;')
的值被设置时,您仍然没有评估y
。这就是y
的值为2
的原因,因为较高范围中变量x
的值为2
。
同样如下:
var x = 2;
function foo() {
var y = x;
console.log(y); //undefined
console.log(x); //undefined
var x = 3;
}
function bar() {
var y = x;
console.log(y); //2
}
var x = 2;
function foobar() {
console.log(x); //undefined
var x;
console.log(x); // undefined
x = 3;
var y = x;
console.log(y); //3
}
eval仅作为正则表达式进行评估。