Make Closure Compiler将几个对象属性声明合并为一个大文字

时间:2012-09-30 17:13:49

标签: javascript properties google-closure-compiler object-literal minify

我将代码分成几个文件,然后运行一个脚本来合并和编译它们(使用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})。
    无效因为,如上所述,我们的想法是创建一些模块化的东西,删除一个文件会使参考中断。

我愿意接受想法!


编辑:有些人可能会认为Closure Compiler无法做到这一点。它可以做到这一点以及更多,只是它有一种不好的态度,并在感觉就好的时候做事。

将此输入Closure:

(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: Closure Compiler bug report

1 个答案:

答案 0 :(得分:0)

我正在做一个解决方法。它可能不适用,所以不能接受这个答案。不过,这就是我的情况。

我的文件夹结构如下所示:

src
├───components
└───core

并且,在编译之前,我合并src/intro.jssrc级别的某些文件(按特定顺序),然​​后合并core中的所有文件(任何顺序),然​​后全部在components(任何顺序),然​​后是outro.js

现在,文件夹结构如下所示:

src
├───components
│   ├───modules
│   └───plugs-literal
└───core
    ├───internal
    ├───modules
    └───plugs-literal

编译顺序是(注意箭头部分):

  • src/intro.js
  • src/core中的几个文件,具体顺序。
  • src/core/internal
  • 中的所有文件
  • src/core/plugs-literal-intro.js < -
  • src/core/plugs-literal < -
  • 中的所有文件
  • src/components/plugs-literal < -
  • 中的所有文件
  • src/core/plugs-literal-outro.js < -
  • src/core/modules
  • 中的所有文件
  • src/components/modules
  • 中的所有文件
  • src/outro.js

这个想法是一个文件包含一个对象文字的开头,另一个文件包含一个对象文字,两个文件夹包含属性。或多或少是这样的:

src/core/plugs-literal-intro.js

var myObjectLiteral = {
    'someSimpleProp': 'foo',
    'someOtherSimpleProp': 'bar',
    'lastOneWithoutTrailingComma': 'baz'

src/core/plugs-literal/EXAMPLE.js

,'example': function() { alert('example'); } // comma before, not after.

src/core/plugs-literal-outro.js

};

如果这引入了一些不必要的问题,我稍后会知道。但是,我可以指定一个不同的文件夹来包含单独声明的原型属性。