我将我的代码分成几个文件,然后运行一个脚本来合并和编译它们(使用ADVANCED_OPTIMIZATIONS
)。大部分功能是在单个对象的原型中实现的。
所以当合并时,它可能看起来像这样:
(function(){
/** @constructor */ function MyConstructor() {};
MyConstructor.prototype = {};
MyConstructor.prototype['foo'] = function() { alert('foo'); };
MyConstructor.prototype['bar'] = function() { alert('bar'); };
MyConstructor.prototype['baz'] = function() { alert('baz'); };
window['MyConstructor'] = MyConstructor;
}());
如果您像这样将该代码放入Closure Compiler中,则输出如下(打印精美):
function a() {
}
a.prototype = {};
a.prototype.foo = function() {
alert("foo")
};
a.prototype.bar = function() {
alert("bar")
};
a.prototype.baz = function() {
alert("baz")
};
window.MyConstructor = a;
问题是,有什么方法可以告诉 Closure Compiler 可以将所有这些合并到一个对象字面量中,即使中间有代码(在这个例子中没有,但可能有) ,所以无论如何,它都会编译成一个大对象文字?
这里有几个解决方案,以及为什么它们对我不起作用:
- 解决方案 1:只需在一个大对象字面量中声明它们。
行不通,因为我将我的代码放入多个文件中,并且我计划制作它,以便用户可以在编译之前删除其中的一些(如果他们不需要它们)。对象文字有逗号分隔符,这会使这成为一场噩梦。 - 解决方案 2:声明对象之外的所有功能(作为闭包中的私有变量),并将它们附加到最后的简化对象字面量中,该字面量仅包含对属性的引用(例如
{'foo':foo,'bar':bar,'baz':baz}
)。
行不通,因为如上所述,这个想法是创建模块化的东西,删除一个文件会使引用中断。
我对想法持开放态度!
编辑:有些人可能认为闭包编译器不能做到这一点。它可以做到这一点,而且做得更多,只是它态度不好,喜欢做就做。
将其输入到闭包中:
(function(){
var MyConstructor = window['MyConstructor'] = function() {};
var myProto = {
'foo': function() { alert('foo'); },
'bar': function() { alert('bar'); }
};
myProto['baz'] = function() { alert('baz'); };
MyConstructor.prototype = myProto;
}());
结果是:
(window.MyConstructor = function() {
}).prototype = {foo:function() {
alert("foo")
}, bar:function() {
alert("bar")
}, baz:function() {
alert("baz")
}};
看?但是,这是代码非常脆弱,如果稍微修改一下,它可能会编译成完全不同的东西(而且不是那么好)。例如,即使是中间某处的变量赋值也可能导致它输出非常不同的结果。换句话说,这不起作用(在这种情况下除外)。
编辑 2:看到这个jsperf。Chrome 中的大对象字面量更快(与其大小成正比)。
编辑 3: 关闭编译器错误报告。