JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptのスコープとは?グローバル・ローカル・レキシカルスコープの違いを徹底解説

この記事では、JavaScriptにおけるスコープの仕組みと、グローバルスコープ・ローカルスコープ・レキシカルスコープという3種類の違いについて、実例コード付きでわかりやすく解説します。

スコープ(Scope)とは、関数や変数にアクセスできる範囲(コンテキスト)のことです。JavaScriptのスコープには、主に以下の3種類があります。

  • グローバル変数: コードブロックの外側で宣言された変数
  • ローカル変数: コードブロックの内側で宣言された変数

覚えておきたいポイント: 関数は、自分の外側で定義された変数や関数にはアクセスできます。しかし、他の関数の内側で定義された変数にはアクセスできません。

この点については、後ほどコード例を見ればすぐに理解できるでしょう。

グローバルスコープ(Global Scope)

グローバルスコープ上にある変数や関数は、他の関数の中からでも自由にアクセスできます。

// グローバルスコープ
let dogBreed = "Labrador"

let getDogBreed = function() {
  // dogBreedはグローバルスコープにあるためアクセス可能
  console.log(dogBreed)
  // "Labrador"
}

// 関数を実行
getDogBreed()

これは、関数の中に入れ子になった関数の場合も同様です。

// グローバルスコープ
let dogBreed = "Labrador"

let getDogBreed = function() {
  // 関数の中の関数
  let getDogBreedFromGlobalScope = function() {
    // グローバルスコープのdogBreedにアクセス
    console.log(dogBreed)
    // "Labrador"
  }
  // 内側の関数を実行
  getDogBreedFromGlobalScope()
}

// 関数を実行
getDogBreed()

ローカルスコープ(Local Scope)

ローカルスコープを持つ変数や関数は、そのスコープ自身の内側からしかアクセスできません。

let getDogBreed = function() {
  // ローカルな変数スコープ
  let dogBreed = "Labrador"
  // ローカル変数なので関数内からアクセスできる
  console.log(dogBreed)
  // "Labrador"
}

変数dogBreedはローカルスコープを持つため、そのスコープ内、つまり波括弧{ .. }の中からしかアクセスできません。

次に、先ほどと同じコードを使って、今度はconsole.log(dogBreed)をローカルスコープの外側(=グローバルスコープ)に移動してみます。

let getDogBreed = function() {
  // ローカルな変数スコープ
  let dogBreed = "Labrador"
}

// ローカルスコープの変数にアクセスしようとする
console.log(dogBreed)
// Uncaught ReferenceError: dogBreed is not defined

すると「dogBreed is not defined(dogBreedは定義されていません)」という参照エラー(ReferenceError)が発生します。これは、グローバルスコープからローカルスコープの変数を参照しようとしたために起こるものです。

レキシカルスコープ(Lexical Scope)

関数をネストする(関数の中に関数を入れる)と、親関数(一番外側の関数)内の変数や関数には、内側の関数からアクセスできます。この仕組みをレキシカルスコープと呼びます。

ただし、逆は成り立ちません。親(外側)の関数から、内側の関数内にある変数や関数にアクセスすることはできません。言葉だけではイメージしにくいため、実際のコード例で確認してみましょう。

// グローバルスコープ
let animals = function() {
  // レキシカルスコープ
  let dogBreed = "Labrador"
  // ネストされた関数
  let getAnimals = function() {
    // dogBreedはレキシカルスコープにあるためアクセス可能
    console.log(dogBreed)
    // "Labrador"

    // こちらはローカルスコープの変数
    let catBreed = "Persian"
    console.log(catBreed)
    // "Persian"
  }
  // ネストされた関数を実行
  getAnimals()

  // dogBreedはレキシカルスコープ内にあるため正常に表示される
  console.log(dogBreed)
  // "Labrador"

  // catBreedはgetAnimals()関数のローカル変数のため、ここでは参照できない
  console.log(catBreed)
  // Uncaught ReferenceError: catBreed is not defined
}

animals()

まとめ

  • グローバルスコープ: プログラム全体からアクセスできる最上位のスコープ
  • ローカルスコープ: 関数などのブロック内でのみ有効なスコープ
  • レキシカルスコープ: 内側の関数から外側の関数の変数にアクセスできる仕組み(逆向きのアクセスは不可)

スコープの仕組みを正しく理解することで、意図しない変数の衝突やエラーを防ぎ、保守性の高いコードを書けるようになります。

  1. OperaでJavaScriptを有効にする方法【初心者向けガイド】

    OperaでJavaScriptを有効にする手順OperaブラウザでJavaScriptを有効にしたい場合は、以下の手順に従って設定を行ってください。1. 設定画面を開くまず、Operaブラウザを起動し、画面左上にあるメニューボタンをクリックします。表示されたメニューの中から「設定(Settings)」を選択してください。2. 「javascript」を検索する設定画面が開いたら、ページ上部にある検索ボックス(設定の検索)に「javascript」と入力します。3. JavaScriptの許可設定を変更する検索を実行すると、JavaScriptに関するオプションが表示されます。ここで「サイトが

  2. JavaScriptでメソッドを借りる方法とは?call()・apply()・bind()の使い方を解説

    JavaScriptでは、call()、apply()、bind() の3つのメソッドを使うことで、他のオブジェクトが持つメソッドを「借りて」実行することができます。このテクニックは「メソッドの借用(Method Borrowing)」と呼ばれ、コードの再利用性を高めるために広く活用されています。call()・apply()・bind() の違いcall():第1引数に this として渡したいオブジェクトを指定し、残りの引数はカンマ区切りで個別に渡します。呼び出し時に即座に実行されます。apply():call() とほぼ同じですが、引数を配列(または配列風オブジェクト)としてまとめて渡す点