JavaScriptで関数内で使う定数や変数の影響範囲ルール(スコープ)について理解を整理しよう

JavaScriptで関数内で使う定数や変数の影響範囲ルール(スコープ)を整理する

スコープとは?

JavaScriptでコードを書く中で、普段意識することはないかもしれませんが、コードの動作がうまくいかない時に知っておかないと痛い目を見る概念に「スコープ」があります。

「スコープ」はいわば「変数・定数の影響範囲」を定義する物です。

letやconstで宣言した変数と定数は、{}で囲まれた範囲「ブロック」が影響範囲になります。

変数・定数が有効な範囲を「スコープ」といい、ブロックのスコープのことを「ブロックスコープ」といいます。

どの書き方が良くて、どの書き方が間違いなのかを場合分けして確認します。

スコープ内の定数・変数の参照

次の例では、定数aはブロックスコープ内で使用されているため、全てのconsole.log()メソッドで20が出力されます。

JavaScript
{
  const a =20;
  //20を出力
  console.log(a);
  {
    //20を出力
    console.log(a);
  }
}

この様「スコープ」内で定義されている定数aはそのスコープ内で利用可能です。また、入れ子になっている深い階層の「スコープ」内でも使用可能です。

スコープの外側からスコープ内の定数・変数の参照

次の例では、console.log()を2回実行し、どちらも同じ定数・変数を参照しようとしていますが、片方はエラーになります。

JavaScript
{
  {
    const a = 20;
    //20を出力
    console.log(a);
  }
  //エラーが発生
  console.log(a);
}

ブロック{}の外側で定数aを使おうとしている箇所があるため、その部分のconsole.log()がエラーになります。

ブロックの中で定数aが宣言されているので、ブロックスコープの外側からアクセスすることができないためです。

これを開発者ツールで実行しても、下記の画像の様にエラーが返ってきます。

スコープの間違い例
スコープの間違い例

もちろん、同じスコープ内のconsole.log()は適切に実行され、20を出力します。

どこからでも参照できるグローバルスコープ

{}で囲まれていないスコープの外側(トップレベル)は「グローバルスコープ」となります。グローバルスコープで宣言した定数・変数は「全てのブロック内で使用が可能」です。

JavaScript
const a = 20;

{
  console.log(a); //結果: 20
}z

関数やif文定義の{}

関数やif文を使うに当たって使われる{}もスコープです。動作方法は何ら変わりなく、{}で定義された定数や変数はその{}内または、その入れ子でのみ参照可能です。

外部から参照するのは不可能です。下記はその一例です。

JavaScript
function targetFunction() {
  const targetValue = 'User A';
  console.log(targetValue); //結果: 'User A'
}
console.log(targetValue); //エラー
Var宣言は使うな

変数を宣言する際、letではなうvarを用いることも可能です。varはletよりも古い変数宣言方法です。

しかし、varを用いた変数の場合はブロックスコープに対応できません、要するにvarで宣言された変数はスコープに関係なくどこからでも呼び出されます。

次の様なコードを実行してもエラーになりません。

JavaScript
function targetFunction() {
  var targetValue = 'User A';
  console.log(targetValue); //結果: 'User A'
}
console.log(targetValue); //varで宣言されているので、エラーにならない

この挙動では、定数・変数のスコープがわかりづらくなり、バグの温床になります。

varは基本的に使用せず、letとconstでコードを書く様心がけましょう。

インストラクター