簡體   English   中英

使用Google Closure編譯器防止將導出的屬性內聯為常量

[英]Preventing inlining of exported properties as constants w/ Google Closure Compiler

這是輸入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;
});

常量內聯非常好,但是考慮到已導出的值,因此內聯的值並不安全。 我已經嘗試使用goog.exportProperty@expose注釋來代替goog.exportSymbol ,並且沒有運氣。

救命? 謝謝!

更新: @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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM