with文 ブロックスコープ
withと言えばオブジェクトを省略できる
例えば
document.write('hoge'); document.getElementById('body'); //↓すっきり with(document){ write('hoge'); getElementById('body'); }
コードの冗長を防げる。
ブロックスコープ
javascriptでは基本的にブロックスコープが存在しない。
(letがあるが、一部のブラウザのみ対応)
var a=1; { var a=2 alert(a); // 2 } alert(a) // 2
withを使って(擬似的に)ブロックスコープを実現
var a=1; with({a:2}){ alert(a); // 2 } alert(a) // 1
ポイントは「無名オブジェクト(リテラル)」{a:2}を生成し、with内では({a:2}).aへアクセスさせていること。
何が言いたいか
以前にこれのwith({e:e})という書式を理解できませんでした。
http://amachang.art-code.org/usrb.in/amachang/static/gaiax01/
for (var i = 0, l = nl.length; i < l; i ++) { var e = nl[i]; with({e:e}) setTimeout(function() { var box = new Box(e); box.start(); }, i * 500); }
仮に、このコード
■with({e:e})がなければ
new Box(e)の引数eはループの都度別の値を参照するのではなく、ループ終了時のnl[nl.length-1]を参照してしまい、setTimeoutで処理しているeは毎回同じ対象となる。
■with({e:e})すると
ループの度に無名オブジェクト{e:e}を作り、({e:e}).eには毎回異なった値nl[i]が代入される。
withに束縛されたsetTimeout内のeはトップレベルの変数eでなく、無名オブジェクトのプロパティeを参照している。
補足
withを使うべきだということではなく、このようなコーディングができることにまた面白さを垣間見た。
withは最適化が難しく、無闇に多様するのはよくないぽい。
そこで現実的には上のコードは無名関数を使って書き直せる
ループの度、使い捨て関数を実行しローカル変数に毎回異なる値を格納する
for (var i = 0, l = nl.length; i < l; i ++){ (function(elm,n){ var e=elm,i=n; // 関数スコープ setTimeout(function() { var box = new Box(e); box.start(); }, i * 500); })(nl[i],i); }