1

这是输入 JavaScript 的最小示例(由另一种语言生成,但既不在这里也不在那里):

goog.provide('foo.bar');
foo.bar.baz = 42;
goog.exportSymbol('foo.bar.baz', foo.bar.baz);
foo.bar.quux = (function quux(){return foo.bar.baz;
});
goog.exportSymbol('foo.bar.quux', foo.bar.quux);

我的期望是,因为foo.bar.baz没有被注释为常量,所以它不会被视为一个常量。然而,高级优化(本地和通过编译器服务)无论如何都会内联它:

var d = this;
function f(g, e) {
  var b = g.split("."), a = d;
  b[0] in a || !a.execScript || a.execScript("var " + b[0]);
  for (var c;b.length && (c = b.shift());) {
    b.length || void 0 === e ? a = a[c] ? a[c] : a[c] = {} : a[c] = e;
  }
}
;f("foo.bar.baz", 42);
f("foo.bar.quux", function() {
  return 42;
});

常量内联很棒,但考虑到它是导出的,有问题的值内联是不安全的。除了 and 而不是 ,我尝试使用goog.exportPropertyand注释,但没有运气。@exposegoog.exportSymbol

帮助?谢谢!

4

1 回答 1

0

更新:@expose现已弃用。用新方法更新了答案。

如您所述,@const对内联没有影响。@const仅表示该值不会更改(仅分配/设置一次)。

@nocollapse是专门为防止财产崩溃而创建的。鉴于:

goog.provide('foo.bar');
/** @nocollapse */
foo.bar.baz = 42;
alert(foo.bar.baz);

在这种情况下,目的@nocollapse是防止编译器将属性折叠为:

var a = 42;
alert(a);

但是,编译器仍然从流分析中知道foo.bar.baz分配了整数42并且从未更改过。因此,它将只使用已知值。

防止内联的唯一可靠方法是导出属性:

goog.provide('foo');
goog.provide('foo.bar');
foo.bar.baz = 42;
goog.exportProperty(foo.bar, 'baz', foo.bar.baz);
alert(foo.bar.baz);

有一个已知的(尽管很小)需要向编译器规定重命名是安全的,但内联不是。请参阅https://code.google.com/p/closure-compiler/issues/detail?id=971

如果您不使用闭包库,则导出将如下所示:

var foo = {};
foo.bar = {};
/** @nocollapse */
foo.bar.baz = 42;
foo.bar['baz'] = foo.bar.baz;
alert(foo.bar.baz);

如果您的目标是确保foo.bar.baz没有内联或重命名,那么您将需要带引号的属性和@nocollapse.

goog.provide('foo');
goog.provide('foo.bar');
/** @nocollapse */
foo.bar.baz = 42;
goog.exportProperty(foo.bar, 'baz', foo.bar.baz);
alert(foo.bar.baz);

如果您将此命名空间提供给其他人使用,那么最好的情况是结合使用@nocollapse以防止崩溃并允许外部更新和goog.exportSymbol.

goog.provide('foo');
goog.provide('foo.bar');
/** @nocollapse */
foo.bar.baz = 42;
goog.exportSymbol('foo', foo);
goog.exportProperty(foo, 'bar', foo.bar);
goog.exportProperty(foo.bar, 'baz', foo.bar.baz); 

alert(foo.bar.baz);
于 2013-11-08T14:32:10.693 回答