2013-05-31 52 views
0

我編譯下面的代碼使用Google Closure Compile ADVANCED_OPTIMIZATIONS:我該如何重寫這個Closure Compile來重命名我的函數?

(function() { 
    /** @const */ 
    var DEBUG = false; 

    var Namespace = {}; 
    window['Namespace'] = Namespace; 

    (function() { 
    /** 
     * @constructor 
     */ 
    function Test(tpl) { 
     Helper.debug('Test'); 
    } 

    Namespace['Test'] = Test; 

    })(); 

    var Helper = 
    (function(){ 
     /** 
     * @constructor 
     */ 
     function Helper(){ 
     this.debug = function(arg){ 
      if(DEBUG){ 
      console.log(arg); 
      } 
     } 
     }; 

     return new Helper; 
    })(); 

})(); 

我的目的是讓編譯器去除所有Helper.debug消息時DEBUG == false,以及調試功能重命名爲短的名稱時DEBUG == true

DEBUG == false

var a={};window.Namespace=a;a.Test=function(){}; 

DEBUG == true:我從編譯器,希望這樣的事情

var a={};window.Namespace=a;a.Test=function(){console.log("Test")}; 

我結束了這個:

DEBUG == false

var a={};window.Namespace=a;a.Test=function(){b.debug("Test")};var b=new function(){this.debug=function(){}}; 

DEBUG == true

var a={};window.Namespace=a;a.Test=function(){b.debug("Test")};var b=new function(){this.debug=function(c){console.log(c)}}; 

在兩種情況下是debug功能重命名。我想它應該是,因爲它不是從Namespace導出,也不可以訪問(據我所知)。它只能從Namespace.Test()的構造函數中調用。如果我不從那裏調用它,Closure會去掉調試函數(因爲它沒有在任何地方使用),但我希望能夠通過名稱空間中的函數調用它,並且仍然會重命名它。

我已經嘗試了上述代碼的各種版本。在Helper上使用prototype.debug,將Helper構造函數移動到與Namespace相同的作用域等等。只要調試函數附加到我的Helper對象上,我找不到從編譯器獲得所需輸出的方法。

如果我不使用Helper對象,並且只是聲明debug作爲函數,那麼我會得到我想要的輸出,但這只是一個示例,我確實有許多函數連接到Helper對象,而我希望他們全部改名爲短名稱。示例代碼,給我我想要的輸出:

(function() { 
    /** @const */ 
    var DEBUG = false; 

    var Namespace = {}; 
    window['Namespace'] = Namespace; 

    (function() { 
    /** 
     * @constructor 
     */ 
    function Test(tpl) { 
     debug('Test'); 
    } 

    Namespace['Test'] = Test; 

    })(); 

    function debug(arg){ 
    if(DEBUG){ 
     console.log(arg); 
    } 
    } 

})(); 
+0

你可以有條件代碼使用goog.DEBUG;如果(goog.DEBUG){..代碼未編譯時設置編譯器--define goog.DEBUG = false ...} – HMR

+0

我不知道如果閉包編譯器與您創建它們的方式創建對象很好。如果使用var Helper = function(){}定義幫助器,調試將被重命名; Helper.prototype.debug = function(){}?或者:var Helper = {debug:function(){}}你的模式看起來像是用於通過閉包創建私有變量的東西,但是在閉包庫代碼中沒有看到它,他們會使用帶有@private註解的this.private_來代替。 – HMR

+0

嗨@HMR感謝您的輸入。我不知道'good.DEBUG',但是我有很多其他函數連接到Helper,我想將其重命名爲短名稱,而不是重命名。我嘗試了兩種初始化Helper的方法,但仍然存在同樣的問題。 – Paulpro

回答

1

我想你的代碼,並發現該名debug不轉換,但其他的名字會。因爲我沒有console.log的extern文件,所以用警報替換了console.log。這是您的修改後的代碼(僅調試改名爲「東西」和執行console.log提醒):

(function() { 
    /** @const */ 
    var DEBUG = false; 

    var Namespace = {}; 
    window['Namespace'] = Namespace; 

    (function() { 
    /** 
     * @constructor 
     */ 
    function Test(tpl) { 
     Helper.something('Test'); 
    } 

    Namespace['Test'] = Test; 

    })(); 

    var Helper = 
    (function(){ 
     /** 
     * @constructor 
     */ 
     function Helper(){ 
     this.something = function(arg){ 
      if(DEBUG){ 
      alert(arg); 
      } 
     } 
     }; 

     return new Helper; 
    })(); 

})(); 

編譯代碼,現在有更多的或預期的輸出(沒有使用構造函數)少:

java -jar compiler.jar --js helper.js --js_output_file out。JS --compilation_level = ADVANCED_OPTIMIZATIONS --formatting = PRETTY_PRINT --warning_level = VERBOSE

(function() { 
    var a = {}; 
    window.Namespace = a; 
    (function() { 
    a.Test = function() { 
    } 
    })() 
})(); 

設置DEBUG爲真給我:

(function() { 
    var a = {}; 
    window.Namespace = a; 
    (function() { 
    a.Test = function() { 
     b.a() 
    } 
    })(); 
    var b = function() { 
    return new function() { 
     this.a = function() { 
     alert("Test") 
     } 
    } 
    }() 
})(); 

請注意,所列性能不會被重命名。因此使用this['something'] = function(arg){Helper['something']('Test');將導致不能重命名的內容。我的猜測是,你已經知道了,因爲你使用的窗口[「namespase」] [「測試」]

[更新]

Closure編譯器不重命名實習醫生中定義的方法。例如,「文檔」在編譯器使用的extern中定義(如果不是每次使用文檔都會導致錯誤)。因此,如果您要將Helper.debug重命名爲Helper.getElementById,它仍然不會重命名它(getElementById在編譯器默認使用的externs文件中定義)。下面是從Oreilly.Closure.The.Definitive.Guide.Sep.2010 391頁來源:

var mystery = function(obj) { 
alert(obj.max()); 
}; 

因爲神祕沒有任何類型的信息,OBJ可能是 無論是內置的數學對象或者一個例子.NumSet。因爲它是 可能Math提供作爲神祕參數,所以 編譯器無法重命名max()方法。因此, 編譯器採用保守的方法來重命名變量,如果它也出現在extern中,則不會重命名變量 。這是 之一,默認情況下,編譯器不包括其他extern 文件(如contrib/externs中的那些文件):將更多 名稱添加到extern池可能會不必要地減少 變量所做的變量的數量編譯器。

即使您提供類型信息,編譯器也不會重命名,而沒有一些額外的標記--use_types_for_optimization。你的代碼仍然不會重命名調試,但這可能是因爲你需要一個typedef。將調試重命名爲myDebug將導致該函數被重命名。

Why does Closure Compiler not rename objects with certain names?

+0

感謝一噸HMR!我嘗試了很多重寫這種方法,我甚至嘗試過'Helper.test',因爲完全相同的原因沒有重命名。我很感謝你爲我回答這個問題所付出的全部努力。 – Paulpro

+0

不客氣。當我讀完這本書時,爲什麼這些功能沒有重新命名,所以我想應該更新答案。 – HMR