考えられる説明の 1 つ:
あなたが言及しているClosure Compilerの機能は「名前空間の平坦化」です。これは、名前空間の長いチェーンでのルックアップに関連するコストを回避しようとするコンパイラの試みです。
たとえばfoo.bar.baz.hello.doSomething();
、プロパティを見つけるには、4 つのオブジェクトのチェーンをナビゲートする必要がありdoSomething
ます。名前空間のフラット化により、プロパティは にフラット化されa
、呼び出しは -- に置き換えられa();
ます。これは大幅な改善です。
したがって、2 番目のケースでは、実際db
に問題になっているのはオブジェクトではありません。次の一連の最適化が行われると思います。
var db = {};
db.col = { One: 0, Two: 3, Three: 4, Four: 1, Five: 2, Six: 7, Seven: 8 };
alert(db.col.Two); alert(db.col.Three); alert(db.col.Four);
名前空間のフラット化:
var a=0, b=3, c=4, d=1, e=2, f=7, g=8;
alert(b); alert(c); alert(d);
次に、b、c、d はすべて 1 回だけ使用されるため、インライン化されます。
var a=0, e=2, f=7, g=8;
alert(3);alert(4);alert(1);
そして最後に、未使用の変数 a、e、f、g が破棄されます。
ただし、これはグローバル スコープでは正常に機能しますが、クロージャー内で定義されたオブジェクトをキャプチャする関数呼び出しがそのクロージャー内にある可能性があるため、コンパイラーはクロージャー内でオブジェクトが定義されている場合は特に注意する必要があります。コンパイラがオブジェクトを「フラット化」してオブジェクトを削除するには、クロージャ内のすべてが「副作用なし」でなければなりません。そうしないと、内部関数呼び出しが参照するキャプチャされたオブジェクトが存在しなくなると、コードが壊れます。
alert()
副作用がないとは考えられていません。したがって、 と はへの呼び出しによって変更される可能性があるdb
と想定されます。その後の潜在的に副作用のないコードは、変更されたorを参照する可能性があるため、これらのオブジェクトを削除してはなりません。 注:呼び出しが副作用のない最後の呼び出しである場合、これは適用されません。db.col
alert
db
db.col
alert()
名前空間のフラット化を有効にするには、オブジェクトをクロージャの外に移動し、キャプチャできないグローバル スコープで定義する必要があります。
- オブジェクト定義を関数クロージャーの外に移動します (したがって、それらを名前空間にします)。
- オブジェクト表記の使用を避ける
これはうまくいきます:
var db = {}; // Put the namespace outside, making it global
db.col = {}; // Put sub-namespaces outside also
(function(){
db.col.One = 0; // Avoid using object notation
db.col.Two = 3;
db.col.Three = 4;
db.col.Four = 1;
db.col.Five = 2;
db.col.Siz = 7;
db.col.Seven = 8;
alert(db.col.Two); alert(db.col.Three); alert(db.col.Four);
})();
1 つの良い実験は次のとおりです。
(function() {
var db = {};
db.col = { One: 0, Two: 3, Three: 4, Four: 1, Five: 2, Six: 7, Seven: 8 };
alert(db.col.Two); // Only one call
var test = db.col.Three + db.col.Four; // This statement is side-effect-free
})();
見よ!できます:
alert(3);
でも:
(function() {
var db = {};
db.col = { One: 0, Two: 3, Three: 4, Four: 1, Five: 2, Six: 7, Seven: 8 };
alert(db.col.Two); // First call, anything afterwards is suspect
alert(db.col.Three); // Oops! Cannot eliminate db or db.col!
})();
動作しません:
var a={a:{f:0,c:3,b:4,e:1,d:2,h:7,g:8}};alert(a.a.c);alert(a.a.b);