MENU

レキシカルスコープとダイナミックスコープの比較

目次

レキシカルスコープとは?

レキシカルスコープ(Lexical Scope)は、変数がどのスコープに属するかを「コードの構造」や「定義された場所」に基づいて決定するものです。JavaScript、Python、Cなどの多くのプログラミング言語はこのスコープの仕組みを採用しています。関数がどこで「定義」されたかが重要であり、その関数が「呼び出される場所」によって変数の参照範囲が変わりません。

let x = 10;

function foo() {
  console.log(x); // このxは、fooが定義された場所のスコープから参照される
}

function bar() {
  let x = 20;
  foo(); // ここで呼び出してもxは10のまま
}

bar(); // 10

上記のコードでは、foobarの中で呼び出されても、fooが定義された場所のスコープ(グローバルスコープ)を参照します。barの中にx = 20があっても、それは無視されます。これは、レキシカルスコープが「定義時のスコープ」を重視するためです。

ダイナミックスコープとは?

一方、ダイナミックスコープ(Dynamic Scope)は「実行時のスコープ」に基づいて変数を解決します。関数が呼び出された「場所」によって、そのスコープが決まります。したがって、ダイナミックスコープでは関数の呼び出し元が変わると、参照される変数も変わります。近年の主流の言語ではあまり使われていませんが、Lispや一部のシェルスクリプトでこの考え方が採用されています。

たとえば、JavaScriptがダイナミックスコープを採用していたとしたら、次のようになります。

let x = 10;

function foo() {
  console.log(x); // このxは、呼び出し元のスコープから参照される
}

function bar() {
  let x = 20;
  foo(); // ダイナミックスコープだとxは20になる
}

bar(); // 20

この場合、foo関数が呼び出される時点のスコープ(barのスコープ)を参照するため、x20となります。つまり、ダイナミックスコープでは、関数の「呼び出し元」のスコープが参照されるのです。

レキシカルスコープ vs ダイナミックスコープ

レキシカルスコープダイナミックスコープ
スコープの決定定義された場所に基づく呼び出し元の場所に基づく
メリットコードの予測可能性が高い実行時の状況に柔軟に対応できる
デメリット柔軟性が低くなる場合があるコードの挙動が予測しにくくなる

レキシカルスコープの最大の利点は、コードを見ただけで変数の参照先がわかり、予測がしやすいことです。一方で、ダイナミックスコープは実行時の状況に応じて変数を解決できるため、柔軟性はありますが、逆にどの変数が参照されるかが分かりづらくなることが多いです。

なぜレキシカルスコープが一般的なのか?

レキシカルスコープが一般的な理由は、その予測可能性と安定性にあります。定義時のスコープが参照されるため、コードを読むだけで変数がどこから来るのか理解しやすく、バグを防ぎやすいからです。

一方で、ダイナミックスコープの柔軟性が求められる場面は、特殊なケースに限られるため、現代のプログラミング言語ではレキシカルスコープが主流となっています。

目次