Javascriptにおけるforループのクロージャって意識したことあるだろうか。
例えばよく出くわすこんなコード。実はこれには問題がある。
for (var i = 0, l = elm.length; i < l; i++;) {
elm[i].addEventListener('click', function() {
console.log(i);
}, false);
}
問題
取得した要素をforループで回してクリックイベントを設定してクリックした時にループのカウントを参照する。
しかしこれだとクロージャが生成されず、カウンタ変数が保持されない為どの要素から参照しても該当するカウントはlength値の値になる。
See the Pen GJwwLM by Youhei Isokawa (@yuhiisk) on CodePen.
※コンソールで確認可能
解決策
ループブロックの中で即時関数を使うとクロージャを生成出来る。
即時関数の引数にカウンタ変数を渡すところがポイントだ。
for (var i = 0; i < length; i++;) {
(function(n) {
elm[n].addEventListener('click', function() {
console.log(n);
}, false);
})(i);
}
See the Pen MwzzMd by Youhei Isokawa (@yuhiisk) on CodePen.
もしあなたがもっとJavaScript Ninjaになりたいなら
同じ問題の解決策がJavascript Ninjaで紹介されていて、なるほどと思った。
この書き方はなかなか思いつかない。forループのブロックに即時関数を指定する。
この方がスッキリ書けるのでオススメだ。
for (var i = 0; i < length; i++;) (function(n) {
elm[n].addEventListener('click', function() {
console.log(n);
}, false);
})(i);