【问题标题】:ReferenceError on Google Chrome but not on Firefox (Browser Bug?)Google Chrome 上的 ReferenceError 但 Firefox 上没有(浏览器错误?)
【发布时间】:2016-12-19 16:56:12
【问题描述】:

这段代码

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

如果

  • eval 未使用,或
  • eval 内的代码被{} 包围,或者
  • a 未在 g 中引用,或者
  • let 改为var,或
  • 代码前加"use strict"

这里发生了什么?

【问题讨论】:

    标签: javascript google-chrome referenceerror


    【解决方案1】:

    调整您的示例,您可以看到发生了什么,虽然命令有点矛盾,但它看起来像一个错误。将 a 定义为函数并记录它而不是 f,然后查看控制台。您会看到使用 a、f 和 g 创建了一个闭包。由于 a 在 g 中被引用,并且 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 内的代码用 {} 括起来:变量是相互关联的 通过块范围。
    • g 中没有引用 a:如果变量没有需要闭包 没有关联。
    • let 改为 var:全局范围内的 var 定义在 全球范围。所以不需要关闭
    • 在代码前添加“use strict”:use strict in eval 防止 要添加到全局范围的变量,因此再次“更容易” 处理。 let 需要与全局函数链接之间没有不匹配。

    【讨论】:

      【解决方案2】:
      eval(`
          "use strict";
          let a = 0;
          console.log(f);
          function f(){
          }
          function g(){
              a;
          }
      `);
      

      在严格模式之外尚不支持块范围的声明(let、const、函数、类)

      【讨论】:

      • let 根据MDN,自 Chrome 49.0 起支持草率模式。
      【解决方案3】:

      看起来是a novel V8 bug!一个更小的测试用例是

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

      当调用还具有重要的词法声明时,变量范围的声明(包括顶级函数声明)没有从非严格的 eval 调用中正确提升。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-27
        • 2012-08-19
        • 1970-01-01
        • 2018-06-10
        • 2017-08-25
        相关资源
        最近更新 更多