【JavaScript入門】JavaScriptのスコープを学ぼう

本章では、JavaScriptのスコープについて解説するよ!

はじめに
「JavaScript入門」は、プログラミングを始めたい方、JavaScriptを勉強したい方向けにJavaScriptの基礎と実践を学ぶシリーズです。

初めての方は、まずこちらからお読みください。

【JavaScript入門】はじめに

本章では、JavaScriptのスコープについて学びます。

スコープとは何か、スコープは何のためにあるのか、グローバルスコープ、ローカルスコープの違いなどを解説します。

本題に入る前に、スコープを理解するためにこちらを確認しておきましょう。

  • スコープとは、変数の有効範囲のこと
  • スコープの中で定義された変数はスコープ内でのみ使うことができ、スコープの外からは使うことはできない
  • スコープの種類には、グローバルスコープとローカルスコープがある
  • グローバルスコープとは、プログラム全体でどこからでもアクセスできる範囲
  • ローカルスコープは関数スコープとブロックスコープに分けることができる
  • 関数スコープとは、関数の中に作られるスコープ
  • ブロックスコープとは、「{}」で作られるスコープ、if文や、for文などに使われる

JavaScriptのスコープを一緒に学ぼう!

サンプルコードをダウンロードしよう

次のリンクから、サンプルコードをダウンロードしてください。

参考 サンプルコードJavaScript入門

サンプルコードをテキストエディタで開いてみよう

「Visual Studio Code」から、先ほどダウンロードしたファイルから「011 スコープ」を選択して開いてみましょう。

開くと次のような画面になります。

サンプルコードをChromeで開いてみよう

サンプルコードの「スタート」の「index.html」をChromeで開いてみましょう。

スコープってなに

プログラミングにおけるスコープとは、変数の有効範囲 のことを言います。

変数の有効範囲とはなんでしょうか。

例えば、次のコードでは変数「apple」を定義しています。

const apple = "りんご"

定義したあとは 「console.log」などで使うことができますね。

const apple = "りんご"
console.log(apple)

そして、この変数は関数の中でも使うことができます。

const apple = "りんご"
// 関数の中でも使うことができる
const logApple = () => {
  console.log(apple)
}

console.log(apple)

では、この変数「apple」を関数の中で定義するとどうでしょうか。

const logApple = () => {
  const apple = "りんご"
  console.log(apple)
}
console.log(apple)

関数の外にある console.log(apple) はエラーになります。

なぜなら、関数の中で定義することによって、変数「apple」の有効範囲は関数の中だけ になるからです。

const logApple = () => {
  const apple = "りんご"
  console.log(apple)
}

// ここでは、apple を使うことはできない
console.log(apple)

このようにスコープとは有効範囲を表し、同じスコープ内の変数を使うことはできますが、別々のスコープになると使えなくなる仕組みになっています。

まとめると、スコープの中で定義された変数はスコープ内でのみ使うことができ、スコープの外からは使うことはできません。

スコープって何のためにあるの

スコープは何のためにあるのでしょうか。

スコープの役割は次のようなものがあります。

  • 同じ変数名の衝突を避ける
  • 効率的なメモリ管理など

同じ変数名の衝突を避ける

JavaScriptでは、別々のスコープだったら同じ名前の変数名を作ることができます。

先ほどの例を見てみましょう。

const apple = "りんご"
const logApple = () => {
  console.log(apple)
}
console.log(apple)

変数は関数の外のスコープで定義がされています。

もし、同じ名前の変数を関数の中に作るとどうなるでしょうか。

const apple = "りんご"
const logApple = () => {
  const apple = "りんご2"
  console.log(apple)
}

logApple()
console.log(apple)

関数の中でも同じ名前の変数を作ることができました。

なぜなら、スコープが異なるからです。

そして、このコードの実行結果は次になります。

実行結果

りんご2
りんご

関数のconsole.logは関数の中の変数を使い、関数の外のconsole.logは外の変数を使っているということです。

変数 関数の外 関数の中
apple りんご りんご2

もし、プログラム全体で一意の変数名しか作れないと大変不便になってしまいます。

このように、JavaScriptはスコープをそれぞれ作ることで、同じ名前の変数を作ることができるのです。

スコープの種類

スコープの種類には、グローバルスコープとローカルスコープがあります。

一つずつ見てみましょう。

グローバルスコープ

グローバルスコープとは、プログラム全体でどこからでもアクセスできる範囲です。

グローバルスコープの変数を作るには、「var」キーワードを用いて定義します。

var apple = "りんご"
const logApple = () => {
  // 関数のスコープでも使うことができる
  console.log(apple)
}

グローバルスコープの変数は、別ファイルからでも参照することができます。

実際に動きをみてましょう。

グローバルスコープを書いてみよう

では、実際にグローバルスコープを書いてみましょう。

グローバルスコープの変数を書く

サンプルコードの「スタート」フォルダの「index.js」を開いてみましょう。

グローバルスコープを書いてみよう」と記述がされています。

その真下に、次のように書いてください。

// グローバルスコープを書いてみよう
var apple = "りんご"

グローバルスコープの変数を使う

次に、サンプルコードの「スタート」フォルダの「index2.js」を開いてみましょう。

グローバルスコープを書いてみよう」と記述がされています。

その真下に、次のように書いてください。

// グローバルスコープを書いてみよう
console.log(apple)

Chromeのコンソールで確認すると、次のように出力されているのが分かります。

index2.js」には、変数「apple」は宣言されていません。

しかし、すでに「index.js」でグローバルスコープの変数が定義されているので「index2.js」でも使うことができるのです。

JavaScriptの読み込む順番

ここで注意が必要なのは、JavaScriptが読み込まれる順番です。

グローバルスコープの変数を使うには、先に定義があるファイルを読み込む必要があります。

先ほどの例だと、「index.js」、「index2.js」の順で読み込まなければなりません。


<!doctype html>
<html>
  <head>
    <metacharset="utf-8">
    <title>関数</title>
  </head>
  <body>
    <p>こんにちは</p>
    <!-- 順番に読みこむ -->
    <scriptsrc="index.js"></script>
    <scriptsrc="index2.js"></script>
  </body>
</html>

もし、これを逆にすると変数が定義されていないのでエラーが発生します。


<!doctype html>
<html>
  <head>
    <metacharset="utf-8">
    <title>関数</title>
  </head>
  <body>
    <p>こんにちは</p>
    <!-- 逆に読み込む -->
    <scriptsrc="index2.js"></script>
    <scriptsrc="index.js"></script>
  </body>
</html>

実行結果:

グローバルスコープの変数は使うべき?

基本的にグローバルスコープの変数は多用しない方がいいでしょう。

なぜなら、他のファイルから意図せず変更される可能性があるからです。

意図せぬ変更はバグを生みやすくなります。

変数のスコープはなるべく、小さくする方 が安全にプログラムを書くことができます。

ローカルスコープ

グローバルスコープの変数以外は、ローカルスコープに分類されます。

さらに、ローカルスコープは関数スコープとブロックスコープに分けることができます。

関数スコープ

関数スコープとは、関数の中に作られるスコープです。

関数内で作られrた変数は関数の外のスコープでは使うことはできません。

const logApple = () => {
  // 関数の中で変数を定義する
  const apple = "りんご2"
  console.log(apple)
}

// ここで変数を使うことはできない
console.log(apple)

ブロックスコープ

ブロックスコープとは、「{}」で作られるスコープです。

ブロックについては、if文の章でやりましたね。

【JavaScript入門】JavaScriptの条件分岐を学ぼう – if文 –

if文や、for文などに使われる「{}」がブロックです。

ブロックの中で作られた変数はブロックの外のスコープからは参照することはできません。

ただし、「const」と「let」に限ります。

var」を使うとブロックの外からでも参照できるので注意してください。

if (true) {
  const apple = "りんご"
}
// ここで変数を使うことはできない
console.log(apple)

「var」を使ったパターン

if (true) {
  var apple = "りんご"
}
// 変数を使うことができる
console.log(apple)

ローカルスコープを書いてみよう

では、実際にオブジェクトを書いてみましょう。

サンプルコードの「スタート」フォルダの「index.js」を開いてみましょう。

ローカルスコープを書いてみよう」と記述がされています。

その真下に、次のように書いてください。

// ローカルスコープを書いてみよう
// 関数スコープ
const logApple = () => {
  const apple2 = "りんご2"
  console.log(apple2)
}
logApple()

// 参照できない
// console.log(apple2)
// ブロックスコープ
if (true) {
  const result = true
  console.log(result)
}
// 参照できない
// console.log(result)

if (true) {
  var result2 = true
  console.log(result2)
}
// 参照できない
// console.log(result2)

for (let i = 0; i < 10; i++) {
  const result3 =+ i;
}
// 参照できない
// console.log(result3)

Chromeのコンソールで確認すると、次のように出力されているのが分かります。

「// 参照できない」となっている箇所のコメントを外すとエラーになるので各自確認してみてください。

// 参照できない
console.log(apple2)

まとめ

本章では、JavaScriptのスコープについて学びました。

最後にもう一度、重要なことを確認しましょう。

  • スコープとは、変数の有効範囲のこと
  • スコープの中で定義された変数はスコープ内でのみ使うことができ、スコープの外からは使うことはできない
  • スコープの種類には、グローバルスコープとローカルスコープがある
  • グローバルスコープとは、プログラム全体でどこからでもアクセスできる範囲
  • ローカルスコープは関数スコープとブロックスコープに分けることができる
  • 関数スコープとは、関数の中に作られるスコープ
  • ブロックスコープとは、「{}」で作られるスコープ、if文や、for文などに使われる

次章は、コールバック関数について解説します。