ここでは、JavaScript における変数のスコープについて説明します。
スコープとは
変数はスコープと呼ばれる有効範囲をもっています。スコープとは、ある変数名を参照したり、変更したりすることのできる範囲を表しています。
ローカルスコープとグローバルスコープ
JavaScript にはローカルスコープとグローバルスコープという2つのスコープが存在します。
ローカルスコープ
関数内で var を用いて宣言された変数はローカルスコープをもち、その変数(ローカル変数と呼びます)は宣言された関数内からのみ参照することができます。次のプログラムはローカルスコープをもつ変数を宣言した例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function f() { var num = 100; // 関数 f() 内で宣言されたローカル変数 alert(num); // 関数内から参照可能 function g() { alert(num); // 宣言された関数の中の関数からも参照可能 } g(); } function h() { var num = 200; // 関数 h() 内で宣言されたローカル変数(2行目の num とは別の変数) alert(num); } f(); // 100, 100 h(); // 200 alert(num); // ReferenceError(関数外からは参照できない) |
関数 f() 内で宣言された変数numと関数h()内で宣言された変数numはそれぞれローカルスコープを持つため、名前は同じでも別物の変数として扱われます。
なお、他の言語のようなブロックスコープは JavaScript にはありません。関数内の if 文や for 文のブロック内で宣言された変数であっても、関数内であれば書き換え可能です。
1 2 3 4 5 6 |
var sum = 0; for(var i = 0; i < 10; i++) { sum += i; } alert(sum); // 45 alert(i); // 10 |
上の例では、変数 i は for 文のブロック内で宣言されているにも関わらず、ブロックの後で参照することができています。
グローバルスコープ
関数の外側で宣言した変数はグローバルスコープをもち、プログラムのどこからでも参照することができます。次の例を見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var num = 100; // グローバル変数 function f(){ alert(num); } function g(){ var num = 300; // ローカル変数 alert(num); // ローカル変数が優先的に参照される } function h(){ num = 200; // グローバル変数を書き換える alert(num); } f(); // 100(グローバル変数を表示) g(); // 300(ローカル変数を表示) h(); // 200(グローバル変数を表示) |
プログラムの先頭で宣言された変数 num はグローバルスコープをもち、他の関数からも参照することができます。このとき、変数 num のことをグローバル変数と呼びます。ただし、上記のプログラムで関数 g() 内で宣言された変数 num はローカルスコープをもつローカル変数です。
ローカル変数への参照ははグローバル変数より優先されます。そのため、関数 g() では関数内で定義されたローカル変数 num が参照され、関数 g() を呼び出すと 300 が表示されます。
グローバル変数はプログラムのどこからでも書き換えられる可能性があるため、乱用することはバグの元となるため注意が必要です。必要なグローバル変数は通常プログラムの先頭に列挙します。
スコープの注意点
関数内で var を用いて宣言された変数はローカルスコープをもちますが、関数内であっても var を用いずに宣言された変数はグローバルスコープをもちます。これは、意図せずにグローバル変数を作り出し、しかも見つけづらいためバグの原因となってしまいます。
このため、変数を宣言する際には、var を用いて宣言することが推奨されています。