【JavaScript】スコープ問題:for文中の i 、グローバル変数になっていませんか?

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 />

これと似たスコープの問題は意外と起こりやすいので、気をつけよう。


プロフィール

コヤナギ トモヤ

まったりウェブ系コーダーしてます。PHP製静的CMS Pickles 2 を開発しています。

RSSフィード

  • このサイトは、 コヤナギ トモヤ の個人サイトです。
  • 個人的な主張や、活動の記録などを掲載しています。 所属する企業、団体、その他の意見や立場を代表するものではありません。
  • 掲載された内容は古くなっている可能性があります。 特に古い記事では、現在の筆者の考えと異なる主張をしていることがありますが、記録としてそのまま残しております。 予めご了承ください。
ページの先頭へ戻る