2016-08-12 71 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需要與全局函數相關聯,不會有任何不匹配。
相關問題