割りとjavaScriptでハマりがちな定番例かとは思いますが、
ご多分に漏れず僕もハマってしまいました。
for文の中に非同期処理を入れる際の落とし穴です。
例えば、Imageオブジェクトのonloadメソッドのような非同期処理を
for文の中に入れようとすると、
for(var i = 0; i < 5; i++){
img[i] = new Image();
img[i].onload = function(){
console.log(i);
};
img[i].src = url;
}
とかって最初は書いちゃうかと思います。
これで、望まれる結果としてはimageのloadが完了した順に
3
4
2
1
5
とかって出力してほしいんですが、実際には
5
5
5
5
5
という結果が出力されます。
これは、console.logが出力している変数iが値そのものではなく、
あくまで参照値としてのiであるためです。
したがって、onloadが発火する際にはfor文が最後まで回りきっているため、全て5が出力されてしまいます。
これを解決するには、もうひとつ関数を作ってiを引数として渡してあげる必要があります。
すなわち、
for(var i = 0; i < 5; i++){
img[i] = new Image();
img[i].onload = finish(i);
img[i].src = url;
function finish(i){
return function(){
console.log(i);
}
}
}
とすることで、望むべき結果を得ることができます。
このfinish関数内のconsole.logは出力している変数iは、
参照値ではなく値そのものを出力しているためです。