概要: このチュートリアルでは、変数の可視性とアクセス可能性を決定するJavaScriptの変数スコープについて学習します。
変数スコープとは
スコープは、変数の可視性とアクセス可能性を決定します。JavaScriptには3つのスコープがあります。
- グローバルスコープ
- ローカルスコープ
- ブロックスコープ (ES6から導入)
グローバルスコープ
JavaScriptエンジンがスクリプトを実行すると、グローバル実行コンテキストが作成されます。
また、関数外で宣言された変数はグローバル実行コンテキストに割り当てられます。これらの変数はグローバルスコープに属し、グローバル変数とも呼ばれます。
次の例を参照してください。
var message = 'Hi';
Code language: JavaScript (javascript)
変数message
はグローバルスコープです。スクリプト内のどこからでもアクセスできます。

ローカルスコープ
関数内で宣言された変数は、その関数に対してローカルです。これらはローカル変数と呼ばれます。例えば、
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
は、グローバル実行コンテキストではなく、関数の関数実行コンテキストにバインドされます。

スコープチェーン
次の例を考えてみましょう。
var message = 'Hi';
function say() {
console.log(message);
}
say();
Code language: JavaScript (javascript)
出力
Hi
この例では、say()
関数内で変数message
を参照しています。内部的には、JavaScriptは次の処理を実行します。
say()
関数の現在のコンテキスト(関数実行コンテキスト)で変数message
を検索します。見つかりません。- グローバル実行コンテキストである外部実行コンテキストで変数
message
を検索します。変数message
が見つかります。
JavaScriptが変数を解決する方法は、現在のスコープで変数を検索し、見つからない場合はスコープチェーンと呼ばれる外部スコープに移動することです。

スコープチェーンの例
次の例を考えてみましょう。
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
この例では、var
、let
、またはconst
キーワードなしでcounter
変数に10を代入し、それを返しました。
関数の外部で、getCounter()
関数を呼び出し、結果をコンソールに表示しました。
この問題は、グローバル変数のリークとして知られています。
内部的には、JavaScriptエンジンは最初にgetCounter()
関数のローカルスコープでcounter
変数を検索します。 var
、let
、または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 defined
Code language: JavaScript (javascript)
関数の'use strict'
の使用方法を以下に示します。
function getCounter() {
'use strict'
counter = 10;
return counter;
}
console.log(getCounter());
Code language: JavaScript (javascript)
ブロックスコープ
ES6は、ブロックスコープで変数を宣言できるlet
キーワードとconst
キーワードを提供します。
一般的に、中括弧{}
が表示される場合は常に、ブロックです。 if
、else
、switch
条件、またはfor
、do while
、while
ループ内の領域です。
次の例を参照してください。
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の変数スコープについて学習しました。