javascript中eval内部的声明

javascript中eval内部的声明,javascript,scope,eval,Javascript,Scope,Eval,考虑以下两个JavaScript片段: var x = 2; function f() { var y = x; eval('var x;'); return y; } vs 唯一的区别是我替换了eval('var x;')带有变量x 第一个返回2,但第二个返回undefined。为什么?语法分析器将变量声明提升到词法范围的顶部。在第二段代码中,它的实际运行方式是: function f() { var x, y; y = x; return y; } 功

考虑以下两个JavaScript片段:

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

唯一的区别是我替换了
eval('var x;')带有
变量x


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

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

function f() {
  var x, y;
  y = x;
  return y;
}
功能声明也被悬挂。最终的效果是,变量声明应该始终包含它出现的整个词法范围。如果变量
x
在函数中的任意位置用
var
声明,则该函数中对
x
的每个引用都指向局部变量


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

因为在第二个示例中,
var
在执行任何其他语句之前被提升*到函数的开头

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

var x = 2;
function f() {
    var x, y
    y = x;
    return y;
}
但是对于第一个表达式,
var x
eval()
表达式的一部分,因此它没有机会像第二个表达式那样被提升



*“吊装”一词不是官方术语。它只是一个人们用来描述这样一个事实的词,即声明发生在任何表达式在执行上下文中被计算之前。函数声明也会被挂起。

这是因为当解释器在函数范围内时,它会将值
未定义的
设置为它内部声明的所有变量(前缀为
var
关键字)。无论您将声明放在何处,如果函数中有变量声明,则变量的值将
未定义
,直到您显式设置它的值为止。在第一种情况下,您有
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
}

eval作为正则表达式进行计算

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
}