Javascriptのfor文の中で関数オブジェクトを定義する際の注意点

Javascriptの関数オブジェクトの定義をfor文の中で行うとき、下記のように書くと変数がすべて最後の値になってしまい、i=10の状態で関数が10回実行されます。

for(var i = 0; i < 10; i++){
    setTimeout(function(){
        alert(i);
    }, 0);
}

setTimeoutを使うような例はあまり無いかもしれませんが、たとえばボタンを10個用意してfor文でそれぞれのボタンにEventListenerを定義したときも同じような動きになります。つまり、どのボタンを押してもi=10の挙動になります。

多少気持ち悪い書き方ですが、For文で関数オブジェクトを定義する関数オブジェクトを定義して実行するように書くと上記の現象を回避できます。

for(var i = 0; i < 10; i++)(function(_i){
    setTimeout(function(){
        alert(_i);
    }, 0);
}(i));