Closure编译器没有从javascript中删除死函数

时间:2013-12-16 16:38:47

标签: google-closure-compiler

我试图让谷歌闭包编译器从我的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!");
})();

让闭包编译器省略日志记录代码的正确方法是什么?这里只是调用一个什么都不做的函数。

1 个答案:

答案 0 :(得分:3)

“log”永远不会消除,原因如下:

要消除“log”,必须将其内联 除非它可以被虚拟化,否则它目前无法内联 除非可以消除歧义,否则它不能被虚拟化 如果超类(https://code.google.com/p/closure-compiler/issues/detail?id=1184)上存在定义,则无法消除歧义 对象是一个超类 Math是一个名称空间,定义为Object Math有属性日志。

您还需要执行以下操作:
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!');
})();