Buzzurlの中の人日記

amachang - JavaScript 入門を最初に見たときは見落としてたんだけど、javascript - 勝手に添削 - JavaScript入門with()は徹底的に避けるべしと言われている部分の奇妙なコードが気になって調べて見た。

var nl = document.getElementById('target02').getElementsByTagName('div');
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);
}
amachang - JavaScript 入門

なんじゃこの with文? と思ったので色々試したり調べたりしてみた。

正しい挙動

withなし版

var nl = document.getElementById('target02').getElementsByTagName('div');
for (var i = 0, l = nl.length; i < l; i ++) {
  var e = nl[i];
  setTimeout(function() {
    var box = new Box(e);
    box.start();
  }, i * 500);
}

えっ?と一瞬思った。

正しい挙動では、3つの■が順番に動くのに、withなし版では最後の■しか動かない。

でもよくよく考えれば当たり前だ。

感覚の目でよ~く見てみろ!

withなし版がsetTimeoutに渡したクロージャが使うeは、全部同じ実行コンテキスト上のeを参照している。しがたってsetTimeoutがクロージャを呼び出すときにはループは終わってeはnl[nl.length-1]を参照してしまっていて、みんなして最後の■を動かしてしまう。つまりキングクリムゾンによって過程はすっ飛ばされ、結果だけが残る

withを使うと、ループ毎に作られる無名オブジェクト{e:e}がスコープチェーンの先頭に追加されるので、withブロックの中では単にeと書くとブロックローカルなe(=nl[i])を参照できるというわけ。つまりwithを使ってCライクなブロックスコープを実現している。これは知らなかった。

参考:JavaScript でブロックスコープを実現する: Days on the Moon

プロフィール
HN:
ajiyoshi
性別:
男性
自己紹介:
プログラマです。
ソーシャルブックマークサービス「Buzzurl」の開発者です。

はてなブックマークカウンタ


旧*「ふっかつのじゅもんがちがいます」カウンタ
Buzzurl

powered by Buzzurl

Twitter

カレンダー
03 2007/04 05
S M T W T F S
1 2 3 4 5 7
8 9 10 11 14
15 16 18 19 20 21
22 23 24 25 26 27 28
29 30
最新コメント
[07/23 つらら]
[07/23 れいら]
[06/16 婚活]
[05/28 あっだ]
[05/28 もも]
最新トラックバック
バーコード
ブログ内検索
忍者ポイント
カウンター
アクセス解析
あわせて読みたい
あわせて読みたい
Powered by ニンジャブログ  Designed by ゆきぱんだ
Copyright c *「ふっかつのじゅもんがちがいます。」 All Rights Reserved
ブログ / [PR]レシピ 中古車査定