我理解eval()在非严格的上下文中是如何工作的,但是eval()在严格模式下使用的情况完全让我迷惑不解.如果eval()是在全球范围内直接调用,变量保存在新的内部eval()范围:
'use strict';
eval('var a = 1;');
console.log(a); // ReferenceError: a is not defined
Run Code Online (Sandbox Code Playgroud)
但是,如果我在全局范围内执行间接调用eval()(应该是同一个东西,对吗?),它就好像它不是在严格模式下(如果你不相信我,请看这个JSFiddle):
'use strict';
(0, eval)('var a = 1;'); // indirect call to eval
console.log(a); // 1???
Run Code Online (Sandbox Code Playgroud)
如果你不明白是什么(0, eval),请参阅为什么谷歌主页使用(0,obj.func)(args)语法?.
至少根据我对如何eval()在严格模式下工作的理解,它意味着(无论eval()是直接还是间接调用)为eval()调用中定义的变量创建一个新的范围,但这似乎不是这里的情况.规范说明如下:
10.4.2输入Eval代码
当控件进入eval代码的执行上下文时,执行以下步骤:
如果没有调用上下文或者eval代码没有通过直接调用(15.1.2.1.1)评估到eval函数那么,
一个.将执行上下文初始化为使用eval代码作为C的全局执行上下文,如10.4.1.1中所述.
其他,
一个.将ThisBinding设置为与调用执行上下文的ThisBinding相同的值.
湾 将LexicalEnvironment设置为与调用执行上下文的LexicalEnvironment相同的值. …
这是一个例子,其中o.foo();3 (p.foo = o.foo)();是2 但是2?
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2”Run Code Online (Sandbox Code Playgroud)
如果我做这样的事情,那么我得到4的就是我想要的东西.这两个例子有何不同?
p.foo = o.foo;
p.foo(); // 4
Run Code Online (Sandbox Code Playgroud)