我使用Google Closure Compile使用ADVANCED_OPTIMIZATIONS编译以下代码:
(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;
})();
})();
我的意图是编译器在DEBUG == false
时删除所有Helper.debug消息,并在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剥离调试函数(因为它没有在任何地方使用),但我希望能够通过Namespace中的函数调用它,并且仍然可以重命名。
我已尝试过上述代码的各种版本。在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 :(得分:1)
我尝试了您的代码,发现名称debug
未转换,但其他名称将被转换。将alert.log替换为alert,因为我没有console.log的externs文件。这是您修改过的代码(仅将调试重命名为'something',将console.log重命名为alert):
(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设置为true会给我:
(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');
会导致某些内容无法重命名。我的猜测是你已经知道了,因为你正在使用window ['namespase'] ['Test']
<强> [更新] 强>
Closure编译器不会重命名externs中定义的方法。例如,“document”在编译器使用的extern中定义(如果不是每次使用document都会导致错误)。因此,如果您要将Helper.debug
重命名为Helper.getElementById
,它仍然不会重命名它(getElementById在编译器默认使用的externs文件中定义)。以下是Oreilly.Closure.TheDefinitive.Guide.Sep.2010第391页的来源:
var mystery = function(obj) {
alert(obj.max());
};
因为神秘没有任何类型信息,所以obj可以 内置的Math对象或example.NumSet。因为它是 可能提供数学作为神秘的论据, 编译器无法重命名max()方法。出于这个原因, 编译器采用保守的方法来永远地重命名变量 如果变量也出现在外部,则重命名变量。这是其中之一 编译器不包含额外外部的主要原因 默认情况下,文件(例如contrib / externs中的文件):添加更多文件 外部池的名称可能会不必要地减少数量 编译器完成的变量重命名。
即使您提供类型信息,编译器也不会在没有额外标志的情况下重命名--use_types_for_optimization。您的代码仍然不会重命名调试,但这可能是因为您需要一个typedef。将调试重命名为myDebug将导致重命名该函数。
Why does Closure Compiler not rename objects with certain names?