公開日: 2009年04月17日(Fri)
JavaScriptの変数のスコープに関連してよく起こりがちなミスとして、for文で使う i の例を挙げる。
例えば次のコード。
<script type="text/javascript">
function test_a(){
for( i = 0; i < 5; i ++ ){
test_b(i);
}
alert('Finished');
}
function test_b(num){
for( i = 0; i < 5; i ++ ){
alert(num+':'+i);
}
}
</script>
<button onclick="test_a();return false;">execute test_a()</button><br />
この実装は誤りである。
test_a() は、再帰的に test_b() をコールしており、それぞれの中で for文 のループが回っている。このとき、test_a() の中で5回、test_b() の中で5回、合計5*5=25回のアラートが出て、最後に"Finish"というアラートが出るのが正しい動作。
しかし、この実装にはバグがあり、5回分しかアラートは出ない。
原因は、i がグローバル変数になってしまっていて、test_a() と test_b() が同じ i を参照しているということ。test_a() の中の初回の処理のときに、test_b() が i を5まで引き上げてしまう。すると、test_a() の二回目のループの条件にマッチせず、1回で break してしまうのだ。
次のように、var
宣言を付加して、 i をローカル変数として定義してやれば、test_a() の i と test_b() の i は別物になり、この問題を回避することができる。
<script type="text/javascript">
function test_a(){
for( var i = 0; i < 5; i ++ ){
test_b(i);
}
alert('Finished');
}
function test_b(num){
for( var i = 0; i < 5; i ++ ){
alert(num+':'+i);
}
}
</script>
<button onclick="test_a();return false;">execute test_a()</button><br />
これと似たスコープの問題は意外と起こりやすいので、気をつけよう。
公開日: 2009年04月17日(Fri)