2016-04-21 81 views
3
(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,只留下:Closure编译器不会删除未使用的属性

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范围的情况下,我需要一些私人persisten变量,并在原来的源对象整齐地划分?也许是一些注释?

这一切都在发布的那一刻最新得到的预建释放测试:

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

你可能需要找到注解给予编译更多的信息,但我想不出如何去做。 Closure编译器更多地面向[古典Java风格的继承模式](http://bolinfest.com/javascript/inheritance.php)。这种编写模块的方式似乎是Closure Compiler的“新前沿”。请参阅https://github.com/google/closure-compiler/wiki/JS-Modules。我希望在Closure Compiler中具有这种“模块样式”经验的人可以帮助你。 – owler

+0

在下面的答案中,我展示了最新版本的Closure Compiler解决了你的问题。我不知道他们什么时候会制作另一个预先编译的编译器,但在本地机器上构建编译器非常简单。步骤是:'git clone https:// github.com/google/closure-compiler.git','ant jar'。 – owler

+0

还有什么需要回答这个问题吗? – owler

回答

3

UPDATE:关闭编译器的最新版本正确minifies你的代码。 online Closure Compiler仍然是一个较旧的版本(我不知道如何知道它是什么版本)。

这说明我使用

$ 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 

的编译器版本这说明我编译代码:

$ 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); 

下面是我较早的答案(现在不相关)。


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

的问题是,“属性”崩溃的唯一全球范围内发生一次报价,那就是发生前函数内联(职权范围内优化循环过程中发生这种情况)。为此,“折叠属性”至少需要再发生一次,否则我们需要增强本地版本的功能,以便能够在全局范围内运行。

您需要修改DefaultPassConfig才能第二次运行CollapseProperties。没有现成的编译器选项来执行此操作。

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

另请参阅Understanding Property Removal

我不清楚您的要求,您似乎正在使用module pattern。如果你并不需要特定的图案此代码:

(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())); 
})() 

使用与先进的优化结果是使用放大模块模式不完全崩溃的代码很好地精缩

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); 

这或许有资格作为一个bug in the compiler

我怀疑你的原始代码崩溃到console.log(14)是有点侥幸。我的猜测是,编译器在编译过程中会执行一些整数运算,而这种情况恰好可以解决。需要注意的是使用非整数会导致你原来的代码不会崩溃(同样使用Math.random()num值时)

(function(){ 
    var num = 4/3; 
    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)) 
})() 

结果:

(function(){var d=4/3,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))})(); 
+0

“另外,”在编写(或使用)这样的代码时,我还会提醒你“总是看一下_general_ case”。作为一个编译器,“聪明”可能永远不会“聪明”。此外:任何你告诉它在任何时候都要做的事情,它注定要每隔一段时间做一次。例如,如果你“修改编译器”来处理“case-X”,编译器会盲目地将同一个mod应用到“cases-Y,Z和Q!也许这就是为什么(!)一些作者......不仅选择不实施特定的选项,而且明确地选择了这样说,“详细地说。” 。 。 。 : - / –

相关问题