【问题标题】:Preserve prototypes in ADVANCED mode在高级模式下保留原型
【发布时间】:2017-07-09 00:34:05
【问题描述】:

我需要在高级模式下使用闭包编译器编译我的代码。我还需要在我的应用程序中保留对象的原型,因为我正在循环使用 Javascript 对象原型。在启动应用程序时尝试同时获取这两个结果会导致一些 ReferenceError。

当使用 ADVANCED 模式编译时,一些原型被移除并被使用对象参数的函数替换以恢复“this”关键字。这是由于 CompilerOptions.java 的 crossModuleCodeMotionNoStubMethods 属性造成的。

编译前的代码示例:

function MyClass() = { // Some code }
MyClass.prototype.someFunc = function() { // Some code calling someOtherFunc };
MyClass.prototype.someOtherFunc = function(someParam) { // Some code };

编译后的代码示例:

function MyCompiledClass = { // Some code }
MyCompiledClass.prototype.someCompiledFunc = function() { // Some code calling someOtherFunc }
function someOtherCompiledFunc(that, someParam) = { // Some code }

我首先尝试使用@this 和@preserve JSDoc 标签来解决问题,但没有成功。使用 @export 不是解决方案,因为函数将保留其原始名称。

我现在找到了两个解决问题的方法:

  1. 重构代码如here
  2. 构建自定义版本的 Closure Compiler,如 here 所示

选项 1 需要对我的代码进行大量修改,并且会降低其可读性,如果这是唯一的解决方案,我将尝试这个。

选项 2 似乎是一个不错的解决方法,但我读到 CompilationLevel.java 上的一些更改可能会违反编译器的一些核心假设。有人可以告诉我,如果将setCrossModuleMethodMotion 从 true 修改为 false,它是否仍然尊重编译器的所有核心假设?

我目前正在构建一个自定义版本的编译器,以检查代码是否正确编译,但即使代码可用,我也需要确保它会被正确混淆。

谢谢!

【问题讨论】:

    标签: javascript google-closure-compiler


    【解决方案1】:

    您指的具体优化通道是DevirtualizePrototypeMethods。阻止优化的最佳方法是使用 @nocollapse 注释。它将允许重命名您的方法,但不允许将其从原型中删除。

    我不能 100% 确定它是否适用于这种情况,但如果不适用,您可以提交问题以解决该问题:https://github.com/google/closure-compiler/issues

    【讨论】:

    • 我在发帖后发现是DevirtualizePrototypeMethods 给我带来了一些麻烦。我刚刚尝试使用@nocollapse,但没有成功。我什至为构造函数描述了@constructor,为原型描述了@this,以将它们与我的构造函数链接。我还检查了编译器版本:20170218.0.0。目前,我的快速修复是在我的闭包编译器自定义版本中将DevirtualizePrototypeMethods 设置为false。因为我的代码是专有的,我该如何帮助您解决问题?除了用户端,我对闭包编译器一无所知;)
    • 我可以说@nocollapse 适用于Javascript 对象属性,例如MyClass.myProperty。但它不适用于MyClass.prototype.myAttribute 等属性。我刚刚遇到了与 javascript 对象属性相同的问题,您的解决方案可以正常工作。
    • 我建议然后提交一个问题。 @nocollapse 是阻止此优化而不阻止重命名的正确方法。
    • 我将创建一个问题。你知道是否有可能在不写@nocollapse的情况下将闭包编译器设置为不折叠原型和属性,例如使用命令选项?我问是因为否则,我将不得不在我的代码中几乎所有地方都写@nocollapse:/谢谢!
    【解决方案2】:

    您可以以相同的方式导出构造函数和原型属性。 例如:

    MyClass = function(name) {
      this.myName = name;
    };
    MyClass.prototype.myMethod = function() {
      alert(this.myName);
    };
    window['MyClass'] = MyClass; // <-- Constructor
    MyClass.prototype['myMethod'] = MyClass.prototype.myMethod;

    https://developers.google.com/closure/compiler/docs/api-tutorial3

    【讨论】:

      猜你喜欢
      • 2022-07-07
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多