4

考虑以下两个 JavaScript 片段:

var x = 2;
function f() {
    var y = x;
    eval('var x;');
    return y;
}

对比

var x = 2;
function f() {
    var y = x;
    var x;
    return y;
}

唯一的区别是我已经替换eval('var x;');var x;.

第一个返回2,但第二个返回undefined。为什么?

4

3 回答 3

5

解析器将变量声明提升到词法范围的顶部。在第二个代码块中,它的实际运行方式是:

function f() {
  var x, y;
  y = x;
  return y;
}

函数声明也被提升。最终结果是变量声明应该被认为总是包含它出现的整个词法范围。如果变量在函数中的任何位置x声明,则该函数中的每个引用都是局部变量。var x

在您的第一个示例中,该eval()行只是一个正则表达式语句,因此它按照它在函数中出现的顺序执行。

于 2012-11-24T20:55:58.470 回答
1

因为对于第二个,在var执行任何其他语句之前,将 * 提升到函数的开头。

所以它就好像你的代码是这样的:

var x = 2;
function f() {
    var x, y
    y = x;
    return y;
}

但是对于第一个, thevar xeval()表达式的一部分,因此它没有机会像第二个那样被提升*。


*“吊装”一词不是官方术语。它只是人们用来描述声明发生在执行上下文中评估任何表达式之前的一个词。函数声明也被提升。

于 2012-11-24T20:56:27.500 回答
1

这是因为当解释器在函数范围内时,它会将值设置undefined为在其中声明的所有变量(以var关键字为前缀)。无论您将声明放在何处,如果函数内部有变量声明,则该变量的值将一直存在undefined,直到您明确设置它的值为止。在第一种情况下eval('var x;'),当设置 的值时,您仍然没有评估y它。这就是为什么值为yis的原因,因为上层作用域中2的变量值为. 这里也一样:x2

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 就像一个正则表达式一样被评估。

于 2012-11-24T20:57:07.380 回答