我最近一直在查看 Google Closure Compiler。我下载了 .jar 文件并进行了试驾。到目前为止,我必须说我印象非常深刻。我当然可以看到它在最小化之外的用处。对 Google 团队的支持!
不过,我确实有一个小小的抱怨。在我看来,就优化而言,您只有两个选择。它是 SIMPLE_OPTIMIZATIONS 或 ADVANCED_OPTIMIZATIONS。前者虽然足够,但恕我直言非常简单。一方面,除非我遗漏了什么,否则所有属性名称都不会受到影响。它也不会删除无法访问的代码。另一方面,后一种选择简直太具有破坏性了。
现在,我对 JavaScript 还很陌生,所以我很可能遗漏了一些东西。如果我说一些愚蠢的话,请随时教育我。也就是说,我可以理解在 JavaScript 中重命名的问题。Google 团队建议使用方括号表示法 (object['property']) 而不是点表示法 (object.property) 来访问您不想更改的属性,并且不要混合使用这两种用法。他们还建议使用以下模式“导出”方法:
MyClass = function(name) {
this.myName = name;
};
MyClass.prototype.myMethod = function() {
alert(this.myName);
};
window['MyClass'] = MyClass; // <-- Constructor
MyClass.prototype['myMethod'] = MyClass.prototype.myMethod;
但是,在某些情况下,您希望混合使用这两种表示法。假设我们正在构建一个游戏。游戏的代码完全隔离在一个闭包中。它不会将任何内容“导出”到全局范围,也不需要这样做。事实上,它真的不应该接触窗口对象。但是,它确实需要从 XML 配置文件中读取一些游戏内属性。
示例 JavaScript:
var TheGreatAdventure = (function(window) {
function Fighter() {
// Private to application
this.id = 42;
// Accessible to XML configuration system
this.name = 'Generic Jen';
this.hitPoints = 100;
this.onAttack = genericFighterAttack;
this.onSpeak = genericFighterSpeak;
...
}
Fighter.publishedProperties = ['name', 'hitPoints', 'onAttack', 'onSpeak']
function genericFighterAttack() {...}
function genericFighterSpeak() {...}
function cassieAttack() {...}
function cassieSpeak() {...}
...
EntityReader = {
...
function readFromXMLNode(attributes, entityClass, entityInstance) {
for (var i = 0; i < attributes.length; i++) {
var attribute = attributes[i];
if (attribute.nodeName in entityClass.publishedProperties)
entityInstance[attribute.nodeName] = bindContext[attribute.value];
}
}
...
}
}(window));
示例 XML 配置文件:
<Fighter name='Custom Cassie' onAttack='cassieAttack' onSpeak='cassieSpeak'/>
不仅上述系统无法分配属性,cassieAttack 和 cassieSpeak 函数将在最小化期间作为死代码被消除!
现在,我无法在整个游戏代码中使用括号表示法访问所有“已发布”属性。即使这样做没有运行时惩罚(不应该有),仍然涉及很多额外的输入,并且(IMO)是一个令人眼花缭乱的东西。有了这样的通用属性,所有内容都会在文本编辑器中显示为字符串,违背了语法高亮的目的!
在我看来,对这些属性的简单@preserve(或类似的)指令将允许在最终程序大小中以最低成本使用 ADVANCED_OPTIMIZATIONS。我错过了什么吗?