关于 ecmascript 5:Eval 真的给 JavaScript 引入了动态作用域吗?

Does Eval really introduce dynamic scoping to JavaScript?

人们说 Eval 为 JavaScript 带来了动态范围,但我不明白这种说法是如何有效的。使用 Eval 使用与调用环境相同的词法环境/变量环境来评估表达式(参考 ECMA 262 v. 5)。表达式的赋值或声明显然是动态的,但我认为说它引入了动态范围是没有道理的。

我说 Eval 没有引入动态范围对吗?


是和不是。

严格来说,不;该语言仍然在词法上运行(除了 this,它始终是动态范围的)。

但是,如果您阅读链接到的整个问题,您会发现提问者正在使用 eval 来模拟动态范围。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var x = 1;

function g() {
    print(x);
    x = 2;
}

function f() {
    // create a new local copy of `g` bound to the current scope
    // explicitly assign it to a variable since functions can be unnamed
    // place this code in the beginning of the function - manual hoisting
    var g = eval(String(g));
    var x = 3;
    g();
}

f();                         // prints 3

print(x);                    // prints 1

模拟动态范围完全可以通过提问者使用它的方式来实现。提问者正在使用 eval 将外部定义的函数实际导入另一个函数的范围。这需要对函数进行字符串化并重新声明它。所以外部定义的函数并没有真正在另一个函数的范围内运行(这个例子并没有真正展示严格意义上的动态范围),因为声明了一个全新的函数。话虽如此,提问者的意图是模拟动态范围,他正在通过 eval 实现这一点。