愛(i)は地球を汚染しやすい
地球はグローバルスコープという意味で。
以前に自分が書いたコードをメンテナンスしていると結構やってしまっている書き方に次の物があります。
arrayという要素数が100の配列をグローバルに宣言して要素をすべて0に初期化するとします。
var array = new Array(100); for (i = 0; i < array.length; i++){ array[i] = 0; }
この書き方の何がまずいかと言うとarray以外にもグローバル変数を使ってしまっていることです。
記事のタイトルでばれていますがiが宣言されず突然使われたためグローバル変数になってしまっています。
(Javascriptではvarを付けて宣言されていない変数はすべてグローバルになるためです。)
その証拠に
var array = new Array(100); for (i = 0; i < array.length; i++){ array[i] = 0; } alert(i); //100がアラートされる
と書くと100がアラートされます。
ちなみにただ単にvarをつけて
var array = new Array(100); for (var i = 0; i < array.length; i++){ array[i] = 0; } alert(i); //やはり100がアラートされる
とやるだけでは結局グローバルでvarをつけて宣言していることに違いはないのでやはり
iはグローバル変数になってしまいます。
そこでiをグローバルにせず配列を初期化したい場合は無名関数を使うと良いです。
var array = new Array(100); (function(){ for (var i = 0; i < array.length; i++){ array[i] = 0; } })(); alert(array[99]); //ちゃんと0がアラートされる alert(i); //iが宣言されていませんというエラーになるか何も起こらない
無名関数と共にiも使いすてるわけです。
ぶっちゃけてしまうと私も含めて個人のHPですべて自分一人の管理の元Javascriptを使う場合、
グローバル変数が多いことで致命的な不具合を生じる事は滅多にないのでスコープなんか気にしなくても結果的にうまく動いてくれる場合が多いのですが、そんな場合でもiのスコープによるトラブルは比較的起こりやすいといえると思います。
次のコードではiをvarを付けず使っています。
function inner(){ var array = ["ゼロ","イチ","ニ"]; for(i = 0; i < array.length; i++){ document.write(array[i]); } } inner();
inner()という関数はarrayという配列の要素を一度ずつ画面に出力する関数でこのコードを実行すると
"ゼロイチニ"と表示されます。
ではこのinner()という関数を5回繰り返して、"ゼロイチニゼロイチニゼロイチニゼロイチニゼロイチニ"
と表示したいと考え次のように書いてしまうとこれは致命的なバグになってしまいます。
//※このコードはバグっているので試してみないでください function inner(){ var array = ["ゼロ","イチ","ニ"]; for(i = 0; i < array.length; i++){ document.write(array[i]); } } for(i = 0; i < 5; i++){ inner(); }
5回繰り返す意図で使われたiとinner関数内のiがどちらもグローバルのiを参照しているため
ループを抜けられなくなってしまうわけです。
最近のブラウザは賢いためこれはヤバイコードが来たということに気づき落ちずに処理をやめ
警告してくれるとは思いますが割りとやってしまいがちな不具合ではないかと思います。
この場合は少なくともどちらか一方のiをローカルとして宣言すれば正しく動いてくれるわけですが
やはりベストな書き方は両方をローカル変数とする
function inner(){ var array = ["ゼロ","イチ","ニ"]; for(var i = 0; i < array.length; i++){ document.write(array[i]); } } (function(){ for(var i = 0; i < 5; i++){ inner(); } })();
ではないかと思います。
「forを使う場合iは意識してローカルにする」ということを私も忘れないようにしたいと思います。