jsではスクリプトの実行時に、内部的にGlobalオブジェクト(グローバルオブジェクト)を生成します。
グローバルオブジェクトとは、グローバル変数やグローバル関数を管理するためにjsが自動的に生成する便宜的なオブジェクトなのです。
グローバル変数/関数ではGlobal.hoge
ではなく、単に
変数名 関数名(引数, ...)
のように参照することが可能です。
実はローカル変数もオブジェクトのプロパティです。
ローカル変数はActivation Object(通称Callオブジェクト)
のプロパティなのです。
Callオブジェクトとは、関数呼び出しの度に、内部的に自動生成されるオブジェクトのことで、
グローバル変数と同様に、関数内で定義されたローカル変数を管理するためにjsが自動的に生成する便宜的なオブジェクトなのです。
このグローバルオブジェクトとCallオブジェクト、プログラマが自ら生成するものではありませんし、呼び出すものでもありません。
意識すらしませんが、これらの存在を理解することで変数が解決されるメカニズムが見えてきます。
それがスコープチェーンです。
スコープチェーンとは、グローバルオブジェクト、Callオブジェクトを生成の順に連結したリストのことをいいます。
jsではこのスコープチェーンの先頭に位置するオブジェクトから順にプロパティ(変数)を検索し、マッチするプロパティが見つかったところでその値を採用しているのです。
var y = 'Global'; function outerFunc() { var y = 'LocalOuter'; function innerFunc() { var z = 'LocalInner'; console.log(z); console.log(y); console.log(x); } innerFunc() } outerFunc() // LocalInner // LocalOuter // x is not defined
この場合3階層のスコープが存在します。
- Callオブジェクト(innerFunc関数のスコープ)
- Callオブジェクト(outerFunc関数のスコープ)
- グローバルオブジェクトのスコープ
スコープチェーンはチェーンの先頭である一番内側の関数(今回は1. innerFunc関数のスコープ )から、
グローバルオブジェクトにかけて指定された変数を検索していきます。
変数x, y, zがそれぞれどのようにして値が決まるのかを見ていきましょう。
xの場合
1, 2, 3の階層どこにも定義がされていないので未定義エラーです。
yの場合
1では定義されていません。
2では定義されているので、'LocalOuter'が値になります。
zの場合
1で定義されているので、'LocalInner'が値になります。
このようにしてスコープチェーンを理解することで変数名が重複した場合でも規則が見えていきます!
まとめ
- グローバルオブジェクトとは、グローバル変数やグローバル関数を管理するためにjsが自動的に生成する便宜的なオブジェクト
- Callオブジェクトとは、ローカル変数を管理するためにjsが自動的に生成する便宜的なオブジェクト
- スコープチェーンとは、グローバルオブジェクト、Callオブジェクトを生成の順に連結したリストのこと
- スコープチェーンはチェーンの先頭である一番内側の関数から、グローバルオブジェクトにかけて指定された変数を検索していき、見つけたところで値を採用する。