2016-08-12 161 views
14

这段代码的ReferenceError在谷歌Chrome,但不是在Firefox(浏览器错误?)

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

在Firefox 48.0正常工作,而在谷歌浏览器52.0.2743.116造成Uncaught ReferenceError: f is not defined(64-位)。

如果

  • eval不使用它也能正常工作的谷歌浏览器,或
  • eval代码是围绕与{},或
  • ag没有被引用,或
  • let更改为var
  • 在代码之前添加

这里发生了什么?

回答

1

看起来像是a novel V8 bug!更最小测试用例是

eval(` 
    var f; 
    let a; 
    ()=>a 
`); 
f; 

可变范围的声明(其包括顶层函数声明)没有得到正确地吊出非严格eval呼叫时呼叫还具有一个非平凡词法声明。

2
eval(` 
    "use strict"; 
    let a = 0; 
    console.log(f); 
    function f(){ 
    } 
    function g(){ 
     a; 
    } 
`); 

块范围的声明(让,常量,函数,类)还不支持外严格模式

+1

根据[MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let#Browser_compatibility),自Chrome 49.0起,马虎模式支持'let'。 – johnchen902

+1

啊...我正在使用v47 ... – strah

5

调整您的例子中,你可以看到发生了什么,并同时命令是位矛盾的,它看起来像一个错误。定义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中引用:如果变量 未链接,则无需关闭。
  • 让利改为VAR:VAR在全球范围的 全球范围内定义。因此,没有必要关闭
  • “使用严格”的代码前加入:使用EVAL严格防止 变量被添加到全球范围内,如此反复,“容易”到 手柄。让let需要与全局函数相关联,不会有任何不匹配。
相关问题