1

我在使用高级优化的 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;

这显然不太理想。

我怎样才能防止这种情况发生?


进一步的实验表明,某些关键字(例如“get”)不会被编译。

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")
}};

我仍然不知道是什么原因造成的。

4

3 回答 3

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的闭包编译器概念有关。extern是在 JavaScript 将运行的环境中预定义的符号,例如在Web 编程的情况下windowdocument因为这些名称在环境中是固定的,所以编译器无法破坏这些名称。

如果查看CommandLineRunner.javaDEFAULT_EXTERNS_NAMES中的列表,您将看到externs文件夹中的文件列表。这些文件的内容定义了编译器知道的外部变量(您也可以添加自己的外部变量)。两者和使用名为(和) 的属性定义类型。默认情况下,编译器不知道in的类型,因此据它所知,可以引用or的实例,在这种情况下,重命名是不安全的。webgl.jsw3c_indexeddb.jsgetWebGLContextAttributesIDBObjectStorethismyClassthisWebGLContextAttributesIDBObjectStoreget

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

于 2011-07-06T04:42:22.563 回答
1

这里的示例来看,您似乎需要在构造函数之外显式导出原型方法:

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;
于 2011-07-04T20:47:32.717 回答
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};

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

于 2011-07-04T20:45:18.667 回答