2013-12-16 32 views
1

我想讓google閉包編譯器從我的javascript中刪除一些日誌函數調用而沒有任何成功。下面是我的測試代碼,再現我所看到的Closure編譯器不能從javascript中刪除死鎖函數

/** @define {boolean} */ 
var ENABLE_LOGGING = true; 

(function() { 
    function obj(name) { 
     this.name = name; 
    } 
    obj.prototype = { 
     log: ENABLE_LOGGING ? 
      function(msg) { console.log(this.name + ': ' + msg); } : 
      function(msg) {} 
    }; 

    var A = new obj('bob'); 
    var B = new obj('tom'); 

    A.log('I am an object!'); 
    B.log('I am another object!'); 
})(); 

當我編譯這與java -jar ./compiler.jar --define ENABLE_LOGGING=false --compilation_level ADVANCED_OPTIMIZATIONS --js test.js,它產生這樣的輸出(漂亮打印的清晰度):

(function() { 
    function a(a) { 
    this.name = a; 
    } 
    a.prototype = {log:function() { 
    }}; 
    var b = new a("tom"); 
    (new a("bob")).log("I am an object!"); 
    b.log("I am another object!"); 
})(); 

什麼是正確的方法獲取閉包編譯器以忽略日誌代碼?在這裏,它正在打電話給一個什麼都不做的功能。

+0

的可能重複[排除調試過程中微小的JavaScript代碼(http://stackoverflow.com/questions/2934509/exclude-debug-javascript-code-during -minification) –

回答

3

「日誌」永遠不會被淘汰,這是爲什麼:

爲了消除「日誌」,它必須被內聯。
目前不能內聯,除非它可以被虛擬化。
除非能夠消除歧義,否則它不能被虛擬化。
如果在超類中存在定義,則無法消除歧義(https://code.google.com/p/closure-compiler/issues/detail?id=1184
對象是超類。
Math是一個名稱空間,定義爲一個Object。
數學有屬性日誌。

您還需要做到以下幾點:
1)拆下IFFE,方法devirtualization僅適用於全局類型定義
2)將ENABLE_LOGGING檢查是在方法內。虛擬化僅適用於函數定義,並在死代碼消除之前發生。

所有這些限制都可以通過使用本地函數定義而不是對象方法來避免。

這樣做的效果你想:

/** @define {boolean} */ 
var ENABLE_LOGGING = false; 

(function() { 
    function obj(name) { 
     this.name = name; 
    } 
    var log = 
     ENABLE_LOGGING ? 
      function(obj, msg) { console.log(obj.name + ': ' + msg); } : 
      function(obj, msg) {}; 

    var A = new obj('bob'); 
    var B = new obj('tom'); 

    log(A, 'I am an object!'); 
    log(B, 'I am another object!'); 
})();