Javascript global.eval无法访问词法范围中的变量。行为是否符合ECMAScript标准?
我有一个JavaScript文件,Javascript global.eval无法访问词法范围中的变量。行为是否符合ECMAScript标准?,javascript,dynamic,closures,eval,interpreter,Javascript,Dynamic,Closures,Eval,Interpreter,我有一个JavaScript文件,e.js var global = Function('return this')(); var i = 1; console.log(eval("100-1")); console.log(eval("i")); console.log(global.eval("100-1")); console.log(global.eval("i")); 当我通过V8执行它时: $ node e.js 99 1 99 undefined:1 i ^ Refere
e.js
var global = Function('return this')();
var i = 1;
console.log(eval("100-1"));
console.log(eval("i"));
console.log(global.eval("100-1"));
console.log(global.eval("i"));
当我通过V8执行它时:
$ node e.js
99
1
99
undefined:1
i
^
ReferenceError: i is not defined
at eval (eval at <anonymous> (/private/tmp/xxxx/e.js:8:20), <anonymous>:1:1)
at eval (native)
at Object.<anonymous> (/private/tmp/xxxx/e.js:8:20)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:902:3
$node e.js
99
1.
99
未定义:1
我
^
ReferenceError:未定义i
评估时(评估时(/private/tmp/xxxx/e.js:8:20),:1:1)
评估时(本地)
反对。(/private/tmp/xxxx/e.js:8:20)
在模块处编译(Module.js:456:26)
在Object.Module.\u extensions..js(Module.js:474:10)
在Module.load(Module.js:356:32)
在Function.Module.\u加载(Module.js:312:12)
位于Function.Module.runMain(Module.js:497:10)
启动时(node.js:119:16)
在node.js:902:3
因此,global.eval
适用于数学运算符,但它无法访问变量i
,而eval
适用于这两种情况
这种行为是V8的限制吗?或者,根据ECMAScript标准,这是预期的行为吗?是的,这是符合规范的行为,表示对
eval
的调用“直接”的一个要求是对eval
的引用“有一个环境记录作为它的基值”。这意味着它不能是由属性访问完成的引用(在这种情况下,拥有的对象将是基值);它必须是一个“裸”函数
这种区别对于以下步骤1至关重要:
- a。如10.4.1.1所述,使用评估代码C初始化执行上下文,如同它是全局执行上下文一样
eval
的间接调用提供了一个全局变量环境,而不是局部变量环境。只有直接呼叫才能访问本地环境
这样做是出于实际实现的原因,因为eval
可以向垃圾收集器发出避免清理任何变量的信号。例如,这里有一个没有eval
的案例:
function foo() {
var a = 5, b = 6, c = 7;
return function() { return a; }
}
var func = foo();
alert(func());
function foo() {
var a = 5, b = 6, c = 7;
return function(exp) { return eval(exp); }
}
var func = foo();
alert(func("b"));
foo
返回的函数在foo
终止后可能会访问a
,但我们可以确定b
和c
在foo
终止后将永远不会再被访问b
和c
可以安全地进行垃圾收集,而a
保持未收集状态
现在是一个带有eval
的案例:
function foo() {
var a = 5, b = 6, c = 7;
return function() { return a; }
}
var func = foo();
alert(func());
function foo() {
var a = 5, b = 6, c = 7;
return function(exp) { return eval(exp); }
}
var func = foo();
alert(func("b"));
通常无法确定eval
表达式exp
是否将引用给定的变量,因此垃圾收集器决不能收集任何变量,以便返回的函数仍然可以使用这些变量
为了确定
eval
正在使用,解析器必须能够可靠地识别对eval
的调用。如果eval
是以一种间接的方式呈现的,比如global[“e”+“va”+“l!”[0]
,规范会说eval
ed代码不能访问任何局部变量,从而避免垃圾收集问题。这是符合规范的行为;我会试着找一个复制品。请参阅和的步骤1,但为什么相同的代码在Google Chrome的JavaScript控制台上工作,而在Node.js上不工作?@user955091这是因为i
在Chrome中不是一个局部范围的变量。节点可能将代码包装在(function(){…})(
中。如果你用谷歌浏览器包装它,你会看到最后的调用也会产生一个错误。