JavaScriptの型とスコープ
これからしばらく備忘録もかねて、JavaScript関連の話題でも書いてみようかと*1 *2。まずはJavaScriptの型とスコープについて*3。
まず、JavaScriptの予約語にも書いたとおり、予約語としてint
やdouble
といった、C系列の言語を知っている人には馴染み深い型を表す予約語が一通り揃っている。でも、これらは現在のJavaScriptでは使用されていない。なぜなら、現在のJavaScriptには変数に型がなく、値に型がある言語となっているからだ。
JavaScriptでは、基本的には変数のスコープとして大域(グローバル)スコープと関数内局所スコープしかなく、ブロックスコープは存在しない。これは、関数内でvar
を使って宣言された変数*4は関数内局所スコープとなり、その関数内であればどこでも使用できることを意味する。以下のコードを例に考えてみよう*5。
var
x =0
;function
func(a) { x = a;// グローバル変数xにaを代入?
for
(var
x =0
; x <3
; x++) { alert(x);// alert関数はアラートダイアログを出す関数
} } func(10
); alert("global x is "
+ x);
var
x =0
;function
func(a) { x = a;// グローバル変数xにaを代入
for
(var
i =0
; i <3
; i++) { alert(i); } } func(10
); alert("global x is "
+ x);
実行してみる
さて、JavaScriptを切っていたりする人のために結果を説明すると、最初の例では0、1、2、global x is 0と順にアラートが出たはずだ。しかし次の例では、0、1、2、global x is 10となったはずである。
これらの違いはfor
文の変数の名前がグローバル変数と同じかどうかだけである。JavaScriptにはブロックスコープがないので、最初の例のfor
文で作った変数xは関数内局所スコープとなり、その関数内ならどこでもアクセス出来てしまう。よってx = a;
のx
はなんとグローバル変数ではなく、関数内で有効な変数xを指していることになる。
更に、
function
func1(a) {// グローバル変数xを関数内で作っている?
x = a;for
(var
x =0
; x <3
; x++) { alert(x); } }function
func2(a) {// グローバル変数xを関数内で作っている
x = a; } func1(10
);// これはエラー
//alert(x);
func2(10
);// これはエラーじゃない
alert(x);
実行してみる
こんなことも起こりうる。
まとめると、JavaScriptにはブロックスコープはなく、ブロックスコープを前提にプログラムを組むとひどい目に合うということ。なにやらJavaScript2.0ではブロックスコープが導入されるらしいけど、いまだにIE5.0を使っている人がいるこの状況ではもうしばらくブロックスコープの恩恵にあずかれそうにない。とりあえずの擬似スコープとして、(function () {...})()
を使う方法とwith
を応用する方法があるが、それはまた機会があれば。
今回はid:m-hiyama:20051209を参考にさせて頂きました。より詳しく載っています。
*1:あまり深くは突っ込まないで、実践的な部分のみを説明するつもり。だから自然と何かしらの言語を知っていることが前提。
*2:JavaScriptのバージョンはtry-catch
が使えるという理由だけで1.3にしようかと。
*3:型の話はほとんどしてないけど・・・
*4:JavaScriptでは変数に型が無いので、変数を宣言するときはvar
(variableの略。変数のこと)キーワードを使用する。更に、var
を省略するとグローバル変数になる。
*5:ここでは、JavaScriptでは関数はfunction
を使用して宣言し、戻り値を指定しないところだけ分かればいい。