Help us understand the problem. What is going on with this article?

いつかあなたが絶対に引っかかる、ある一つのJavaScriptの罠

More than 5 years have passed since last update.

JavaScriptは、シンプルな仕様が美しい言語です。
しかしながら、シンプルが故に、一度罠にハマると見つけにくくて抜け出すのが大変です。

罠にハマった時に、すぐに抜け出せるように、簡単な例で抑えておきましょう。

ある一つのJavaScriptの罠が入ったコード

罠が入ったサンプルコードがこちら。

sample
for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i);
    }, 0);
}

コンソールに i という変数を出力しています。

出力はどのようになりますか?

これ、実行したらどのような出力になると思います?
0、1、2と答えたあなた。わたしはそんな素直なあなたが大好きです。
2、2、2と答えたあなた。素晴らしい。JavaScriptを極めてますね!ただ、不正解。ケアレスミス。

出力の答え

こたえは3、3、3。不思議ですね。
さて、なぜこうなるかを解説しましょう。

罠の解説

罠の本質。クロージャとsetTimeout

JavaScriptにはクロージャという仕組みがあります。簡単に言うと、変数が生きつづける仕組みです。
これとsetTimeout という処理を後から実行する仕組みのコンビネーションでこれが発生します。

処理の解説

for 分の中で変数 i は0、1、2と増えて行きます。
しかしながらconsole.logへの出力はsetTimeout の中で行われるため、for文のループが回っている最中は実行されません。なのでconsole.log(i)の i は、ループ中はまだ値として解釈されません。
iが3になってループが終わり、setTimeout が実行される順番が来るとそこで始めて i の中身が出力されるので、出力は3,3,3となるのです。

予言しよう!あなたはいつか、この罠を踏む。

クロージャもsetTimeoutも、JavaScriptには欠かせない重要な機能です。
しかしながら、よくよく理解していても、この罠をちょくちょくふむことがあります。
「あれー。なんかループの中のデータがおかしい!」とか、「ん?変数の値が上書きされてる!」とかいう事態が起きたら、この投稿を思い出してください。
サンプルコードは、ループとsetTimeout で例にあげましたが、この罠はその他の組み合わせ、クリックと通信処理など、他の組み合わせでも発生します。

Why do not you register as a user and use Qiita more conveniently?
  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
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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