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にすればいいのか?
混ぜるな危険ってことですね...