今日の無限ループ
次のようなコードを書いたら、IE6で無限ループに!
// テスト用オブジェクト function Test() {} Test.prototype = { a: function() {}, b: function() {} } var test = new Test(); // for .. inでループ → IE6だと無限ループに! for ( var i in test ) { document.getElementById( "stdout" ).innerHTML += i + "<br/>"; test[i + "_org"] = function(){}; }
IE6のfor .. inループでは、ループ中に追加したプロパティも列挙されてくる模様。なので、ループ中でオブジェクトにプロパティを追加していくと、無限ループに陥ります。↓みたいに直して実行するとわかりやすい。
function Test() {} Test.prototype = { a: function() {}, b: function() {} } var test = new Test(); // for .. inでループ var count = 0; for ( var i in test ) { document.getElementById( "stdout" ).innerHTML += i + "<br/>"; test[i + "_org"] = function(){}; // 無限ループの抑制。100回まで! count++; if ( count > 100 ) { break; } }
Safari3.1,FireFox2.0,Opera9.26でも試してみたけど、ループ開始時に存在したプロパティのみ列挙され無限ループにはなりませんでした。手持ちの環境ではIE6だけっぽい。(IE7や8は試してないです。)
ECMA Scriptの仕様(日本語訳だけど)では「列挙中オブジェクトに新しいプロパティが追加されるならば、新たに追加されたプロパティは現在の列挙において挙げられることを保証されない。」(→Under Translation of ECMA-262 3rd Edition 日本語訳)となっていて、どっちになるかは保証されていないとのこと。ふむ。