谷歌闭包编译器的高级优化并不是优化一些变量

时间:2011-07-04 20:05:35

标签: javascript google-closure-compiler

我遇到了使用高级优化的Google Closure Javascript编译器的问题。正如文档所示,为了保留导出的Javascript,我做了类似这样的事情:

var myClass = function() {
   this["myFunc"] = this.myFunc;
   this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
    myFunc: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

问题在于,无论出于何种原因,有时myFuncmyFunc2都不会缩短,我在最终输出中看到这样的代码:

x.myFunc=x.myFunc;x.myFunc2=x.myFunc2;

这显然不太理想。

如何防止这种情况发生?


进一步的实验表明,某些关键字,例如“得到”没有被编译。

var myClass = function() {
   this["get"] = this.get;
   this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
    get: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

编译成

function a() {
  this.get = this.get;
  this.myFunc2 = this.a
}
window.myClass = a;
a.prototype = {get:function() {
  alert("myFunc")
}, a:function() {
  alert("myFunc2")
}};

我仍然不知道是什么导致了它。

3 个答案:

答案 0 :(得分:4)

我不能复制你的问题。如果我转到http://closure-compiler.appspot.com/home并编译以下内容:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// ==/ClosureCompiler==

var myClass = function() {
  this["myFunc"] = this.myFunc;
  this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
  myFunc: function() { alert("myFunc"); },
  myFunc2: function() { alert("myFunc2"); }
};

然后我得到以下结果:

function a(){this.myFunc=this.a;this.myFunc2=this.b}window.myClass=a;a.prototype={a:function(){alert("myFunc")},b:function(){alert("myFunc2")}};

按预期重命名属性。

至于你的第二个例子,它与名为externs的Closure Compiler概念有关。 extern 是将在运行JavaScript的环境中预定义的符号,例如在Web编程的情况下为windowdocument。因为这些名称在环境中是固定的,所以编译器不能破坏这些名称。

如果查看CommandLineRunner.java中的DEFAULT_EXTERNS_NAMES列表,您会看到externs文件夹中的文件列表。这些文件的内容定义了编译器知道的外部实例(您也可以添加自己的外部实例)。 webgl.jsw3c_indexeddb.js都定义了具有名为getWebGLContextAttributesIDBObjectStore的属性的类型。默认情况下,编译器不知道thismyClass的类型,因此就其所知,this可以引用WebGLContextAttributes或{{的实例1}},在这种情况下,重命名IDBObjectStore是不安全的。

通过使用类型注释(例如get)和编译器选项(例如@constructorambiguateProperties)的组合,编译器可以确定disambiguateProperties将始终引用this的新实例,并始终将其对myClass的所有引用重命名。您可以在 Closure:The Definitive Guide 的第14章中阅读有关这些编译器优化的更多信息。

答案 1 :(得分:1)

example here开始,您需要在构造函数之外显式导出原型方法:

var myClass = function() {};
myClass.prototype = {
    myFunc: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

window["myClass"] = myClass;
myClass.prototype["myFunc"] = myClass.prototype.myFunc;
myClass.prototype["myFunc2"] = myClass.prototype.myFunc2;

这似乎与宣传的一样,虽然对我来说似乎是一个奇怪的优化(所有重复的“原型”引用都添加了很多字节):

function a(){}a.prototype={a:function(){alert("myFunc")},
b:function(){alert("myFunc2")}};
window.myClass=a;
a.prototype.myFunc=a.prototype.a;
a.prototype.myFunc2=a.prototype.b;

答案 2 :(得分:0)

原因在于,使用ADVANCED_OPTIMIZATIONS,GCC将myObject [“a”]与myObject.a区别对待。请尝试以下方法:

var myObject = {};
myObject.attr1 = 3;
myObject["attr2"] = 4;
window["myObject"] = myObject;

它将使用ADVANCED_OPTIMIZATIONS编译到此:

window.myObject={a:3,attr2:4};

我想你会看到你现在需要做什么。