这段代码
eval(`
let a = 0;
function f() {}
function g() { a; }
console.log(f);
`);

在Firefox 48.0上正常运行,同时在Google Chrome 52.0.2743.116(64位)上导致Uncaught ReferenceError: f is not defined
。
如果
,它也适用于Google Chromeeval
未使用,或eval
内的代码包含{}
或a
未在g
或中引用
let
已更改为var
或"use strict"
这里发生了什么?
答案 0 :(得分:5)
调整你的例子,你可以看到发生了什么,虽然命令有点矛盾,但它看起来像一个bug。将 a 定义为函数并将其记录而不是 f ,然后查看控制台。你会看到用 a,f和g 创建了一个闭包。由于g中引用了 a ,并且f和g应该彼此可见,因此它有点意义。但是eval在全球范围内起作用。因此,当您尝试访问它们时,您将得到未定义。就像这个闭包不能从任何地方访问。
尝试:
eval('let a = function(){}; function f() {};function g(){a;};console.dir(a);');
你会在控制台中看到这个:
<function scope>
Closure
a: function()
f: function f()
g: function g()
所有其他案例都会使情况更加清晰,并防止出现问题:
答案 1 :(得分:2)
eval(`
"use strict";
let a = 0;
console.log(f);
function f(){
}
function g(){
a;
}
`);
在严格模式之外尚不支持块范围的声明(let,const,function,class)
答案 2 :(得分:1)
看起来像是a novel V8 bug!一个更小的测试用例是
eval(`
var f;
let a;
()=>a
`);
f;
当调用也有一个非常重要的词法声明时,变量范围的声明(包括顶级函数声明)无法从非严格eval
调用中正确提升。