Google Chrome 上的 ReferenceError 但 Firefox 上没有(浏览器错误?)
ReferenceError on Google Chrome but not on Firefox (Browser Bug?)
这段代码
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 Chrome if
上也能正常工作
eval
未使用,或
eval
里面的代码被{}
包围,或者
a
未在 g
或 中引用
let
改为var
,或
"use strict"
代码前加
这里发生了什么?
eval(`
"use strict";
let a = 0;
console.log(f);
function f(){
}
function g(){
a;
}
`);
Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
调整你的例子你可以看到发生了什么,虽然命令有点矛盾,但它看起来像一个错误。将 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()
你所有的其他情况都使情况更清楚,并防止了问题:
- 未使用eval:范围不匹配不太明显,
- eval 中的代码被 {} 包围:变量是链接的
通过块作用域。
- a 未在 g 中引用:如果变量
没有链接。
- let 改为var:var在全局范围内定义在
全球范围。所以不需要关闭
- "use strict"代码前加: use strict in eval prevents
要添加到全局范围的变量,所以再次 "easier" 到
处理。 let 需要与全局函数链接之间没有不匹配。
看起来是 a novel V8 bug!一个更小的测试用例是
eval(`
var f;
let a;
()=>a
`);
f;
当调用也有非平凡的词法声明时,变量范围的声明(包括顶级函数声明)没有从非严格的 eval
调用中正确提升。
这段代码
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 Chrome if
上也能正常工作eval
未使用,或eval
里面的代码被{}
包围,或者a
未在g
或 中引用
let
改为var
,或"use strict"
代码前加
这里发生了什么?
eval(`
"use strict";
let a = 0;
console.log(f);
function f(){
}
function g(){
a;
}
`);
Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
调整你的例子你可以看到发生了什么,虽然命令有点矛盾,但它看起来像一个错误。将 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()
你所有的其他情况都使情况更清楚,并防止了问题:
- 未使用eval:范围不匹配不太明显,
- eval 中的代码被 {} 包围:变量是链接的 通过块作用域。
- a 未在 g 中引用:如果变量 没有链接。
- let 改为var:var在全局范围内定义在 全球范围。所以不需要关闭
- "use strict"代码前加: use strict in eval prevents 要添加到全局范围的变量,所以再次 "easier" 到 处理。 let 需要与全局函数链接之间没有不匹配。
看起来是 a novel V8 bug!一个更小的测试用例是
eval(`
var f;
let a;
()=>a
`);
f;
当调用也有非平凡的词法声明时,变量范围的声明(包括顶级函数声明)没有从非严格的 eval
调用中正确提升。