Closure编译器不会删除未使用的属性

时间:2016-04-21 12:28:05

标签: javascript google-closure-compiler

(function(){
    var num = 4 // Math.random()
    var module1 = {};

    (function(export_to){
        export_to.add1 = function(arg) { return arg+1 }
        export_to.add2 = function(arg) { return arg+2 }
        export_to.add10 = function(arg) { return arg+10 }
    })(module1)

    console.log(module1.add10(num))
})()

这是原始的内联“模块”示例。只要num不变,GCC就会正确地内联add10函数并使用--compilation_level=ADVANCED删除其他所有内容,只留下:

console.log(14);

结果。

//更改为&&会使GCC表现得更糟。出于某种原因,它不再内联.add10而不再注意.add1.add2根本没有被调用,实际上是死代码。

(function(){var d=Math.random(),c={};(function(b){b.b=function(a){return a+1};b.c=function(a){return a+2};b.a=function(a){return a+10}})(c);console.log(c.a(d))})();

有没有办法让GCC消除/内联这些函数,同时仍然将它们保留在自己的function范围内,以防我需要一些私有持久变量并整齐地分组在原始源中的Object中?也许是一些注释?

这一切都在发布时的最新可用预发布版本上进行了测试:

Closure Compiler (http://github.com/google/closure-compiler)
Version: v20160315
Built on: 2016/03/25 11:43

1 个答案:

答案 0 :(得分:3)

更新:最新版本的Closure Compiler正确缩小了您的代码。 online Closure Compiler仍然是旧版本(我不知道如何判断它是什么版本)。

这显示了我正在使用的编译器的版本

v

这显示了我正在编译的代码:

array = string.split('<br>')
hash = Hash[array.map {|el| el.split('<=>') }]

这显示了编译命令和结果:

intent.putExtra("profileName",profileName.getText().toString());

以下是我之前的回答(现在无关紧要)。

您遇到了Closure Compiler的一些限制。以下是Closure Compiler Issue 891: missed property collapsing opportunity

的引用
  

问题是“属性”折叠仅对全局范围发生一次,即在函数内联发生之前(在优化循环期间发生的函数内)。为此,“崩溃属性”至少需要再次出现,或者我们需要增强本地版本的功能才能在全局范围内运行。

     

您需要修改DefaultPassConfig以再次运行CollapseProperties。没有现成的编译器选项可以执行此操作。

所以可能有办法修改Closure Compiler来处理你的情况。这是一篇关于如何开始修改编译器的博客文章:High-level overview of a compilation job

另见Understanding Property Removal

我不清楚您的要求,您似乎使用了module pattern。如果您不需要该特定模式,则此代码有效:

$ java -jar ../javascript/closure-compiler/build/compiler.jar --version
Closure Compiler (http://github.com/google/closure-compiler)
Version: v20160315-213-g4787bb5
Built on: 2016/04/25 10:12

使用online Closure Compiler和高级优化的结果很好地缩小了

$ cat test2.js
(function(){
    var num = Math.random();
    var module1 = {};

    (function(export_to){
        export_to.add1 = function(arg) { return arg+1 }
        export_to.add2 = function(arg) { return arg+2 }
        export_to.add10 = function(arg) { return arg+10 }
    })(module1)

    console.log(module1.add10(num))
})()

但是使用扩充模块模式并不会完全破坏代码,尽管它确实会进行一些内联​​。这是一个例子:

$ java -jar ../javascript/closure-compiler/build/compiler.jar 
    --js test2.js --compilation_level ADVANCED
console.log(Math.random()+10);

高级优化的结果是

(function() {
var Adder = {};
Adder.add1 = function(arg) { return arg+1; }
Adder.add2 = function(arg) { return arg+2; }
Adder.add10 = function(arg) { return arg+10; }

console.log(Adder.add10(Math.random()));
})()

这可能属于bug in the compiler

我怀疑你的原始代码崩溃到console.log(Math.random()+10); 有点侥幸。我的猜测是编译器在编译期间执行了一些整数运算,这种情况恰好可以解决。请注意,使用非整数会导致原始代码无法折叠(与使用var module1 = {}; module1 = (function(export_to){ export_to.add1 = function(arg) { return arg+1 } export_to.add2 = function(arg) { return arg+2 } export_to.add10 = function(arg) { return arg+10 } return export_to; })(module1); console.log(module1.add10(4)) 作为var b={},b=function(a){a.a=function(a){return a+1};a.c=function(a) {return a+2};a.b=function(){return 14};return a}(b);console.log(14); 的值时相同)

console.log(14)

结果:

Math.random()