这是输入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
没有注释为常量,所以它不会被视为一个常量。然而,高级优化(本地和通过compiler service)无论如何都会内联它:
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;
});
常量内联很棒,但是有问题的值在内联时是不安全的,因为它是导出的。除了goog.exportProperty
之外,我已经尝试使用@expose
和goog.exportSymbol
注释,而没有运气。
帮助?谢谢!
答案 0 :(得分: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);