Closure Compilerを使用したときのオブジェクトメンバに関する注意点

Closure Compilerでスクリプトを最適化する場合、変数名等は短縮されてしまいます。
そのため、例えばオブジェクトのメンバー参照時に問題がおこることがあります。
例えば、Object(連想配列)の初期化時と参照方式に、文字列添字のみ等を使った場合は問題がおこらないのに、
初期化時のメンバー名と参照方式を混在した場合は、正しくメンバーを参照できない問題が発生します。

確認

ということで、Closure compilerの出力結果を確認してみました。


元のスクリプト

var obj = {
  name1: 'foo',   // メンバー名(key)が最適化時に短縮される
  'name2': 'bar'  // こっちはそのまま
};

var result = 'obj.name1: ' + obj.name1;
result += '<br />';
result = 'obj["name2"]: ' + obj['name2'];
result += '<br />';
//ADVANCED_OPTIMIZATIONの時に正しくメンバー参照できない
result = 'obj.name2: ' + obj.name2;  
result += '<br />';
result += 'obj["name1"]: ' + obj['name1']; 

SIMPLE_OPTIMIZATINOS

var obj = {name1:"foo", name2:"bar"}, result = "obj.name1: " + obj.name1;
result += "<br />";
result = 'obj["name2"]: ' + obj.name2;
result += "<br />";
result = "obj.name2: " + obj.name2;
result += "<br />";
result += 'obj["name1"]: ' + obj.name1;

ADVANCED_OPTIMIZATIONS

var a = {a:"foo", name2:"bar"}, b = "obj.name1: " + a.a;
b += "<br />";
b = 'obj["name2"]: ' + a.name2;
b += "<br />";
b = "obj.name2: " + a.b;
b += "<br />";
b += 'obj["name1"]: ' + a.name1;

なんだと...

追試

ではこれは?

メンバー名が非文字列のみ

元のコード

// メンバー名(key)は短縮される
var obj = {
  name1: 'foo',
  name2: 'bar'
};

var result = 'obj.name1: ' + obj.name1;
result += '<br />';
result += 'obj.name2: ' + obj.name2;
result += '<br />';
// メンバー名が非文字列なのでADVANCED_OPTIMIZATIONSで短縮されてしまうので最適化後エラー
result += 'obj["name1"]: ' + obj['name1'];
result += '<br />';
result = 'obj["name2"]: ' + obj['name2'];

ADVANCED_OPTIMIZATIONS

var a = {a:"foo", b:"bar"}, b = "obj.name1: " + a.a;
b += "<br />";
b += "obj.name2: " + a.b;
b += "<br />";
b += 'obj["name1"]: ' + a.name1;
b += "<br />";
b = 'obj["name2"]: ' + a.name2;
メンバー名が文字列のみ

元のコード

// メンバー名(key)は短縮されない
var obj = {
  'name1': 'foo',
  'name2': 'bar'
};

var result = 'obj["name1"]: ' + obj['name1'];
result += '<br />';
result = 'obj["name2"]: ' + obj['name2'];
result += '<br />';
// メンバー名が文字列なので、ADVANCED_OPTIMIZATIONSでメンバー名(key)は短縮されないので最適化後参照エラー
result += 'obj.name1: ' + obj.name1;
result += '<br />';
result += 'obj.name2: ' + obj.name2;

SIMPLE_OPTIMIZATIONS

var obj = {name1:"foo", name2:"bar"}, result = 'obj["name1"]: ' + obj.name1;
result += "<br />";
result = 'obj["name2"]: ' + obj.name2;
result += "<br />";
result += "obj.name1: " + obj.name1;
result += "<br />";
result += "obj.name2: " + obj.name2;

ADVANCED_OPTIMIZATIONS

var a = {name1:"foo", name2:"bar"}, b = 'obj["name1"]: ' + a.name1;
b += "<br />";
b = 'obj["name2"]: ' + a.name2;
b += "<br />";
// メンバー名が文字列なので、ADVANCED_OPTIMIZATIONSでメンバー名(key)は短縮されないので最適化後参照エラー
b += "obj.name1: " + a.a;
b += "<br />";
b += "obj.name2: " + a.b;

結論

  • 文字列添字は短縮されない
  • 非文字列添字は短縮される

Closure-library単体で、WebAPI Libraryとして作成した場合は、
オブジェクトのメンバーにドット参照でアクセスしていなければADVANCED_OPTIMIZATIONSをかけて、
jQueryとかその他Libraryが混在してそうなアプリ側のスクリプトは、SIMPLE_OPTIMIZATIONSにすればいいのか?


混ぜるな危険ってことですね...