2

我将我的代码分成几个文件,然后运行一个脚本来合并和编译它们(使用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: 关闭编译器错误报告

4

1 回答 1

0

我正在做一个解决方法。它可能不适用,因此无法接受此答案。尽管如此,这仍然适用于我的情况。

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

src
├───components
└───core

而且,在编译之前,我合并src/intro.js了该级别的一些文件src(按特定顺序),然​​后是(任何顺序)中的所有文件,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

};

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

于 2012-09-30T21:47:18.550 回答