概要: このチュートリアルでは、変数の可視性とアクセス可能性を決定する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 definedCode 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の変数スコープについて学習しました。