JavaScriptは構文スコープを持つ言語
変数のスコープは、変数が定義されているソースコード行の集合と考えられる。
グローバル変数は、プログラム全体で有効
ローカル変数は、宣言された関数全体と、その関数内に入れ子にされた関数群全体で有効
JavaScriptのコードには、そのコードに関連付けられたスコープチェーンが存在すると考えられる。
このスコープチェーンとは、そのコードに対して「スコープ内」にある変数を定義するオブジェクトのリスト(=チェーン)のこと。
JavaScriptが変数xの値を調べる必要がある場合(この処理を変数の名前解決と呼ぶ)チェーンの先頭のオブジェクトから検索を始める。
このオブジェクトがxという名前のプロパティを持つ場合、そのプロパティの値が使われる。
最初のオブジェクトがxという名前のプロパティを持たない場合、チェーンの次のオブジェクトに対して検索を行い、
次へ次へと検索を進めていく。
スコープチェーンのどのオブジェクトにもxという名前のプロパティが存在しない場合、ReferenceErrorが発生する。
トップレベルコード中(関数に含まれていないコード部分)では、
スコープチェーンに含まれるオブジェクトはグローバルオブジェクト1つだけ。
入れ子になっていない関数の場合、スコープチェーンには、2つのオブジェクトが含まれる。
先頭のオブジェクトには、関数の引数やローカル変数が定義され、
2番目のオブジェクトがグローバルオブジェクト
入れ子になった関数では、3個以上のオブジェクトが含まれる。
このオブジェクトのチェーンは次のように作成される。
まず、関数が定義された時に、現在有効なスコープチェーンを保存しておく。
関数が呼び出された時には、新たにオブジェクトを生成し、ローカル変数を保存する。
そして、この新しいオブジェクトを保存しておいたスコープチェーンに追加し、
関数呼び出し時のスコープチェーンを表す新たなスコープチェーンを生成する。
入れ子にされた関数の場合、外側の関数が呼び出されるたびに、内側の関数が再び定義される。
参考書籍: