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);
}