代码之家  ›  专栏  ›  技术社区  ›  Hobblin

谷歌关闭在高级模式下调用未定义的函数

  •  2
  • Hobblin  · 技术社区  · 12 年前

    使用谷歌闭包编译器,我发现在某些情况下,它会调用未定义的本地函数。我发现的显示这一点的最小例子是:

    var apa = {
        /** @this {!Object} */
        foo: function () { this.bar(id()); },
        bar: function (x) { return [x]; }
    };
    
    apa.foo();
    

    编译为

    (function(){this.a(id())})();
    

    使用编译时 closure --compilation_level ADVANCED_OPTIMIZATIONS 。默认编译(没有任何选项)编译为:

    var apa={foo:function(){this.bar(id())},bar:function(a){return[a]}};apa.foo();
    

    在最低版本中 this.a 未定义。

    在我的研究过程中,我没有发现任何导致这种行为的原因,老实说,我对此感到非常困惑。这是一个即将结束的错误,还是我做出了某种错误的假设?

    (任何关于如何解决这个问题的建议都将不胜感激,因为我非常需要在不手动的情况下尽可能地减少js)。

    1 回复  |  直到 12 年前
        1
  •  3
  •   Chad Killingsworth    12 年前

    您的示例中有几点会导致问题:

    1. 这个 id 函数未在代码示例中定义。编译器将假定它是一个外部函数。当 VERBOSE 如果设置了警告级别,则会针对这种情况发出警告或错误。
    2. 您正在使用 this 构造函数或原型方法之外的关键字。由于编译器可以一直将财产展平为全局变量,从而将 关键字引用可能会更改。
    3. 这个 @this 注释告诉编译器 函数中的关键字将是一个非null对象。我相信你用这个来平息编译器发出的关于前一点的警告。然而,现在您有责任明确设置 对象调用函数时使用 call apply 。此外,该物业 bar 未在类型上定义 Object 因此编译器将更加混乱。

    以下是您的示例的更正版本:

    function id() {
      // this definition was created as an illustration and to prevent the 
      // example from being removed as dead code.
      var id_ = math.random();
      window.console.log(id);
      return id_;
    }
    
    var apa = {
      foo: function () {
        apa.bar(id());
        // id could also be called externally as follows:
        // apa.bar(window['id']());
      },
      bar: function (x) { return [x]; }
    };
    
    apa.foo();
    

    为了进一步了解这些问题,我建议阅读: