JavaScriptの変数スコープ

概要: このチュートリアルでは、変数の可視性とアクセス可能性を決定するJavaScriptの変数スコープについて学習します。

変数スコープとは

スコープは、変数の可視性とアクセス可能性を決定します。JavaScriptには3つのスコープがあります。

  • グローバルスコープ
  • ローカルスコープ
  • ブロックスコープ (ES6から導入)

グローバルスコープ

JavaScriptエンジンがスクリプトを実行すると、グローバル実行コンテキストが作成されます。

また、関数外で宣言された変数はグローバル実行コンテキストに割り当てられます。これらの変数はグローバルスコープに属し、グローバル変数とも呼ばれます。

次の例を参照してください。

var message = 'Hi';Code language: JavaScript (javascript)

変数messageはグローバルスコープです。スクリプト内のどこからでもアクセスできます。

JavaScript Global Variables

ローカルスコープ

関数内で宣言された変数は、その関数に対してローカルです。これらはローカル変数と呼ばれます。例えば、

var message = 'Hi';

function say() {
    var message = 'Hello';
    console.log(message);
}

say();
console.log(message);
Code language: JavaScript (javascript)

出力

Hello
Hi

JavaScriptエンジンがsay()関数を実行すると、関数実行コンテキストが作成されます。 say()関数内で宣言された変数messageは、グローバル実行コンテキストではなく、関数の関数実行コンテキストにバインドされます。

JavaScript Local Variables

スコープチェーン

次の例を考えてみましょう。

var message = 'Hi';

function say() {
    console.log(message);
}

say();
Code language: JavaScript (javascript)

出力

Hi

この例では、say()関数内で変数messageを参照しています。内部的には、JavaScriptは次の処理を実行します。

  • say()関数の現在のコンテキスト(関数実行コンテキスト)で変数messageを検索します。見つかりません。
  • グローバル実行コンテキストである外部実行コンテキストで変数messageを検索します。変数messageが見つかります。

JavaScriptが変数を解決する方法は、現在のスコープで変数を検索し、見つからない場合はスコープチェーンと呼ばれる外部スコープに移動することです。

JavaScript Scope Chain

スコープチェーンの例

次の例を考えてみましょう。

var y = 20;

function bar() {
    var y = 200;

    function baz() {  
        console.log(y);
    }

    baz();
}

bar();
Code language: JavaScript (javascript)

出力

200

この例では、

  • まず、JavaScriptエンジンはbaz()関数のスコープ内で変数yを検索します。見つからないため、このスコープから外に出ます。
  • 次に、JavaScriptエンジンはbar()関数で変数yを検索します。 bar()関数のスコープ内で変数yが見つかるため、検索を停止します。

グローバル変数のリーク: JavaScriptの奇妙な部分

次の例を参照してください。

function getCounter() {
    counter = 10;
    return counter;
}

console.log(getCounter());Code language: JavaScript (javascript)

出力

10

この例では、varlet、またはconstキーワードなしでcounter変数に10を代入し、それを返しました。

関数の外部で、getCounter()関数を呼び出し、結果をコンソールに表示しました。

この問題は、グローバル変数のリークとして知られています。

内部的には、JavaScriptエンジンは最初にgetCounter()関数のローカルスコープでcounter変数を検索します。 varlet、またはconstキーワードがないため、counter変数はローカルスコープでは使用できません。作成されていません。

次に、JavaScriptエンジンはスコープチェーンに従って、グローバルスコープでcounter変数を検索します。グローバルスコープにもcounter変数がないため、JavaScriptエンジンはグローバルスコープにcounter変数を作成します。

この「奇妙な」動作を修正するには、スクリプトの先頭または関数の先頭で'use strict'を使用します。

'use strict'

function getCounter() {
    counter = 10;
    return counter;
}

console.log(getCounter());Code language: JavaScript (javascript)

これで、コードはエラーをスローします。

ReferenceError: counter is not definedCode language: JavaScript (javascript)

関数の'use strict'の使用方法を以下に示します。

function getCounter() {
    'use strict'
    counter = 10;
    return counter;
}

console.log(getCounter());Code language: JavaScript (javascript)

ブロックスコープ

ES6は、ブロックスコープで変数を宣言できるletキーワードとconstキーワードを提供します。

一般的に、中括弧{}が表示される場合は常に、ブロックです。 ifelseswitch条件、またはfordo whilewhileループ内の領域です。

次の例を参照してください。

function say(message) {
    if(!message) {
        let greeting = 'Hello'; // block scope
        console.log(greeting);
    }
    // say it again ?
    console.log(greeting); // ReferenceError
}

say();Code language: JavaScript (javascript)

この例では、ifブロックの外部で変数greetingを参照しており、エラーが発生します。

このチュートリアルでは、関数スコープ、グローバルスコープ、ブロックスコープを含むJavaScriptの変数スコープについて学習しました。

このチュートリアルは役に立ちましたか?