今回は、JavaScriptにおける変数のスコープについてマスターしていきましょう。
スコープとは
スコープとは、宣言した変数の有効範囲のことと思ってもらえればOKです。
JavaScriptでは、関数やブロックごとに別々のスコープが作られるので、スコープが違えば、それぞれの変数は別ものになります。
スコープの種類について解説していきましょう。
グローバルスコープ
プログラムの一番上、トップレベルで宣言された変数、定数はグローバルスコープになります。
グローバルスコープとは、関数や、if文、for文の中など、プログラムのどこからでもアクセスできるスコープと思ってもらえればOKです。
let num = 1; if(true) { console.log(num) // 1 }
if文の中から参照することができ、
let num = 1; function show() { console.log(num); } show();
関数の中からも参照することもできます。
ローカルスコープ
グローバルスコープではないスコープは、すべてローカルスコープと呼ばれます。
ローカルスコープには、関数スコープとブロックスコープがあります。
関数スコープ
関数の中でvar, let, const
を使用して変数・定数を宣言すると、関数スコープと呼ばれます。
関数内で宣言した変数、定数は、その宣言した関数内のみ有効になり、
その関数の外からアクセスすることができません。
const show = () => { let num = 1; console.log(num) // 1 } show();
これは参照されますが、
const show = () => { let num = 1; } console.log(num) // Uncaught ReferenceError: num is not defined show();
関数の外からアクセスすることはできません。
ブロックスコープ
{ } で囲まれた中のスコープはブロックスコープになります。
具体的にはif文、for文、while文、switch文など、これらはすべてブロックスコープになります。
ブロックスコープの中で宣言された変数、定数はブロックスコープの中でのみ、有効になります。
if(true) { let num = 1; console.log(num); // 1 }
これはOKです
if(true) { let num = 1; } console.log(num); // Uncaught ReferenceError: num is not defined
ブロックスコープ外からはアクセスできません。
for (let index = 0; index < 3; index++) { console.log(index); // 0, 1, 2 } console.log(index); // Uncaught ReferenceError: index is not defined
for文もブロックスコープなので、for文の中で宣言されたindex という変数は、for文の外からはアクセスできません。
var はブロックスコープとして使用できない
var で変数を宣言した場合、ブロックスコープとしてスコープを使用することができません。
先ほどのfor文の中で宣言したindexという変数をvarで宣言した際の挙動を確認してみましょう。
for (var index = 0; index < 3; index++) { console.log(index); // 0, 1, 2 } console.log(index); // 3
このようにvar で宣言した場合は、for文の外からアクセスすることが可能です。
var はブロックスコープとして使用することができないことは覚えておいてください。
ブロックスコープは、{ } だけで作れる
ブロックスコープを宣言したいためだけに、即時関数を宣言される方もいると思うのですが、ブロックスコープはif文、for文などを使用せずとも{ } だけで作成することができます。
{ let num = 1; } console.log(num); // Uncaught ReferenceError: num is not defined
案外知られていないことと思うので、ぜひ覚えておいてください。
windowオブジェクトのプロパティ
グローバルスコープで宣言された変数はwindowオブジェクトのプロパティとして取得することができます。
windowとは、グローバルで使えるJavaScriptの関数や変数などが格納されているオブジェクトだと思ってもらえればOKです。(今の時点で深く考えなくて大丈夫です)
let name = "tanaka"; console.log(window.name); // tanaka
このようにwindowオブジェクトのプロパティとしてアクセスすることができます。
使うことはほとんどないと思いますが、知っておくとJavaScriptの理解が深まると思います。
var, let, const をつけずに変数を宣言すると自動的にグローバルスコープ
if(true) { name = 'tanaka'; } console.log(name); // tanaka
このようにvar, let, const をつけずに変数、定数を宣言すると、自動的にグローバルスコープとして認識します。
ただ、この書き方は可読性が悪く、バグにつながるので、変数を宣言する場合は必ずvar, let をつけて宣言するようにしましょう。
グローバルスコープは可読性が悪く、バグにつながる
グローバルスコープで宣言された変数は、変数の宣言場所が分かりにくく、誤って上書いてしまうリスクもあり、思いもよらぬバグにつながる可能性があります。
グローバル変数は、可読性が悪く、バグにもつながるので、なるべく使わないよう意識してみてください。
グローバルスコープはなるべく使わない