このコミットで、実質的な定数をうまく推論できるようになった。(現在のmasterではデフォルト有効になっている)
以下のいずれかの条件を満たしたとき、その変数を定数とみなす。
- "well-defined"かつ一度しか代入されていない
- @const アノテーションが付いている
- const キーワードで宣言されている
- 命名規約によって定数であることがわかる
ルール1の"well-defined"な変数とは、その変数が使用される前に値が代入されることが、コンパイル時に確定できること。(ReferenceCollectingCallback#isWellDefined())
ルール2は従来どおりの通常の動作。
ルール3はES6 constキーワードによる定数宣言。ただし現状のmasterではまだconstキーワードは使えない(正確にはパーサーは対応済みだがコードジェネレーター側が対応していない)。
ルール4は、デフォルトで使われる ClosureCodingConvention) では定数の命名規約が定義されていないため実際には関係ない。(ソースを修正して GoogleCodingConvention#isConstant() を使えばアッパーケースが定数とみなされるようになる)
つまり、従来と比べて実質ルール1が追加になっている。これにより従来アノテーションを書いていた個所で省略しても推論してくれるようになった。
具体的には、以下の場面でアノテーションを明示する必要がなくなった。
var c1 = goog.string.Const.from('文字列リテラルを直接引数に渡す'); // これは従来方式
/** @const */
var s2 = '@const アノテーション';
var c2 = goog.string.Const.from(s2); // これも従来方式
var s3 = '文字列リテラルを変数に代入してから渡す'; // これがルール1で定数とみなされるようになった!
var c3 = goog.string.Const.from(s3); // ので、これがエラーにならなくなった。
他は、変数にクラスを代入して型アノテーションに指定する場合。型指定は定数じゃないと使えない。
/** @constructor */
var Foo = function() {
};
// ここで@constアノテーションが不要に
var Bar = Foo;
/** @type {Bar} */
var b;
これは特にCommonJSで書く場合に有効。
// ここで毎回@constを書く必要がなくなる
var Hello = require('./hello');
/**
* @type {Hello}
*/
var h = new Hello();