レキシカルスコープの基本概念
レキシカルスコープとは、関数がどこで定義されたかによって変数の参照範囲が決まる仕組みです。これは「静的スコープ」とも呼ばれます。
JavaScriptでは、関数が実行される場所ではなく、コードが書かれた位置によってスコープが決定されます。
具体例で理解する
const globalVar = 'グローバル';
function outer() {
const outerVar = '外側';
function inner() {
const innerVar = '内側';
console.log(innerVar); // '内側'
console.log(outerVar); // '外側'
console.log(globalVar); // 'グローバル'
}
inner();
}
outer();
この例では、inner関数は自分自身のスコープ、親のouter関数のスコープ、さらにグローバルスコープの変数にアクセスできます。これがレキシカルスコープの動作です。
スコープチェーンの仕組み
JavaScriptは変数を探す際、以下の順序で検索します。
このように内側から外側へと順番に探していく仕組みを「スコープチェーン」と言います。
クロージャとの関係
レキシカルスコープを理解すると、クロージャの動作も明確になります。
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
返された関数はcreateCounterの実行が終了した後も、count変数にアクセスできます。これは関数が定義された時点のスコープを保持しているためですね。
ダイナミックスコープとの違い
参考までに、レキシカルスコープと対比される「ダイナミックスコープ」について触れておきます。ダイナミックスコープでは関数がどこで呼び出されたかによってスコープが決まりますが、JavaScriptはこの方式を採用していません。
const value = 'グローバル';
function showValue() {
console.log(value);
}
function test() {
const value = 'ローカル';
showValue();
}
test(); // 'グローバル' が出力される
もしダイナミックスコープだったら'ローカル'が出力されますが、JavaScriptはレキシカルスコープなのでshowValueが定義された場所のスコープを参照し、'グローバル'が出力されます。
まとめ
レキシカルスコープの重要なポイントは以下の3つです。
- 変数の参照範囲は関数が定義された場所で決まる
- 内側のスコープから外側のスコープへと順に変数を探す(スコープチェーン)
- この仕組みがクロージャの基盤となっている
この概念を理解することで、JavaScriptのスコープに関する挙動を正確に予測できるようになります。