変数のスコープ(有効範囲)

変数にはそれを参照できる有効範囲があるが、JavaScriptにはどこでも参照できるグローバル変数と呼ばれるものもある。参照とは変数の値を取得するなどの意味で使う。一見、どこからでも自由に参照できるなら全ての変数をグローバル変数にしたらよいと思うかもしれないが、これは管理が大変になったりバグの要因にもなりうる。
その辺りを今回解説しよう。
変数の種類
以前にも見せた画像だ。

varは2014年以前にletとconstは2015年以降に出てきた変数を宣言する時に使うキーワードだったな。この2種類は仕様が少し異なる。
変数のブロックスコープ
変数の有効範囲をスコープと言う。if文などのブロック { } の中にある変数の有効範囲について。
varのブロックスコープ
varは有効範囲が非常に広い。例えば下記のコードはOKだ。
// プログラムは実行できる
{
var x = 100;
}
{
alert(x);
}
上記コードは上と下の部分で別の範囲なのにプログラムは上から下へ順に評価され、最終的に「100」というメッセージが表示される。
letとconstのブロックスコープ
上のコードをvarからletやconstに置き換えてみる。今回はletとした。
// プログラムはエラーとなる
{
let x = 100;
}
{
alert(x);
}
このコードは実行するとエラーとなる。letとconstの方が有効範囲が狭くバグが起こりにくい。
letとconstのブロックスコープの利点
let x1 = 100;
let x2 = 200;
let x3 = 300;
if(true) {
let y1 = 10;
let y2 = 20;
}
if(y2 > 10) {
alert(x2);
}
何をやりたいのか分からないこのコードはエラーとなる。
if(y2 > 10)
このプログラマは実はx2の打ち間違いでy2と書いてしまったが、letを使っていた為にバグにはならずエラーとなりプログラムは止まったのだ。もし下記のようにvarを使って変数を宣言していたら、このコードはエラーとならず意図しない動作となり、バグ探しが大変になったかもしれない。
if(true) {
var y1 = 10;
var y2 = 20;
}
letとconstのブロックスコープについて
letとスコープは外側にある変数を内側のブロックで参照できる。例えば下記のコードだ。
{
let x = 100;
{
alert(x);
}
}
このコードは実行できる。内側にあるブロックはそれより上で囲われたブロックで宣言された変数を参照する事ができるので覚えておこう。if文などでよく使うぞ。
下記のコードのように逆はダメ!
// このコードはエラーになる
{
{
let x = 100;
}
alert(x);
}
内側のブロックで宣言された変数は外側のブロックから参照する事はできない!
関数スコープ
関数は後からレクチャーするが、関数のスコープはvarもletもconstもそのブロックの中だけで参照できる。
// エラーになる
function f1() {
var x = "Test";
}
alert(x);
上記の関数のコードはvarでもエラーとなる。