Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[JavaScript] forの中でコールバックが発生する場合は要注意

More than 5 years have passed since last update.

forループの中で外部処理系からのコールバックが発生する場合は、ループ変数だけが一気に変化するので注意が必要です。 ここでいう『外部処理系からのコールバック』とは、たとえばAjax等を利用してWebからデータを取得したり、KiiCloud等を利用してmBaaSからデータを取得したりする場合を指します。

churippu_s.png 悪い例

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

churippu_s.png 良い例1:ループ変数を受け取る関数でラップ

JavaScript
// 良い例1:ループ変数を受け取る関数でラップする
for(var i in abc) {
    wrap(i);
    function wrap(n) {
        // コールバックが発生する外部処理
        external(function() {
            alert(abc[n]); // a→b→c の順に正しく表示される(※)
        });
    }
}

(※)実際の外部処理系では順不同です

churippu_s.png 良い例2:例1を無名関数化

JavaScript
// 良い例2:ループ変数を受け取る無名関数でラップする
for(var i in abc) {
    (function(n) {
        // コールバックが発生する外部処理
        external(function() {
            alert(abc[n]); // a→b→c の順に正しく表示される(※)
        });
    })(i);
}

(※)実際の外部処理系では順不同です

churippu_s.png デモソース

デモソースはこちら

(・o・ゞ いじょー。

yasumodev
「長い旅行に必要なのは大きなカバンじゃなく、口ずさめる一つの歌さ」スナフキン
https://twitter.com/yasumodev
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away