forループの中で外部処理系からのコールバックが発生する場合は、ループ変数だけが一気に変化するので注意が必要です。 ここでいう『外部処理系からのコールバック』とは、たとえばAjax等を利用してWebからデータを取得したり、KiiCloud等を利用してmBaaSからデータを取得したりする場合を指します。
悪い例
JavaScript
// テスト用配列
var abc = ["a","b","c"];
// 悪い例
for(var i in abc) {
// コールバックが発生する外部処理
external(function() {
alert(abc[i]); // c→c→c と3回表示されてしまう
});
}
//============================================
// 外部処理系のつもり(Web接続、DB接続などを想定)
//============================================
function external(callback) {
setTimeout(callback, 1000);
}
良い例1:ループ変数を受け取る関数でラップ
JavaScript
// 良い例1:ループ変数を受け取る関数でラップする
for(var i in abc) {
wrap(i);
function wrap(n) {
// コールバックが発生する外部処理
external(function() {
alert(abc[n]); // a→b→c の順に正しく表示される(※)
});
}
}
(※)実際の外部処理系では順不同です
良い例2:例1を無名関数化
JavaScript
// 良い例2:ループ変数を受け取る無名関数でラップする
for(var i in abc) {
(function(n) {
// コールバックが発生する外部処理
external(function() {
alert(abc[n]); // a→b→c の順に正しく表示される(※)
});
})(i);
}
(※)実際の外部処理系では順不同です
デモソース
(・o・ゞ いじょー。