2016-04-21 23 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!也許這就是爲什麼(!)一些作者......不僅選擇不實施特定的選項,而且明確地選擇了這樣說,「詳細地說。」 。 。 。 : - / –

相關問題