是的,这是符合规范的行为。ES5 15.1.2.1.1,直接调用 Eval,表示调用的一个要求eval
“直接”是指eval
"有环境记录作为其基础值.” 这意味着它不能是通过属性访问完成的引用(在这种情况下,拥有的对象将是基值);它必须是一个“裸”函数。
这种区别对于步骤 1 至关重要10.4.2, 输入评估代码:
- If there is no calling context or if the eval code is not being evaluated by a direct call (15.1.2.1.1) to the eval function then,
- A。使用 eval 代码作为 C 来初始化执行上下文,就像它是全局执行上下文一样,如 10.4.1.1 中所述。
因此,间接调用eval
给出的是全局变量环境,而不是局部变量环境。只有直接调用才能访问本地环境。
这样做是出于实际实施的原因,因为eval
可以向垃圾收集器发出需要避免清理任何变量的信号。例如,这是一个没有的情况eval
:
function foo() {
var a = 5, b = 6, c = 7;
return function() { return a; }
}
var func = foo();
alert(func());
返回的函数foo
可能会访问a
after foo
终止,但我们可以确定b
and c
之后将永远不会再被访问foo
终止。b
and c
可以安全地进行垃圾收集,同时a
仍未收集。
现在有一个案例eval
:
function foo() {
var a = 5, b = 6, c = 7;
return function(exp) { return eval(exp); }
}
var func = foo();
alert(func("b"));
不可能一般地决定是否eval
表达exp
将引用给定的变量,因此垃圾收集器必须never收集任何变量,以便它们仍然可供返回的函数使用。
为了决定eval
在使用中,解析器必须能够可靠地识别对eval
。如果eval
以间接的方式呈现,例如global["e"+"va"+"l!"[0]]
,规范说eval
ed 代码无法访问any局部变量,从而避免垃圾收集问题。