変数や関数の実行コンテキストでアクセスできるデータ及び動きが決められる。そして実行コンテキスト毎に「変数オブジェクト」という物を紐付けている、実行コンテキストの中で宣言した変数と関数はその「変数オブジェクト」の中に存在している。外部では直接「変数オブジェクト」をアクセスできないが、内部で使われている。
ブラウザの中ではグローバルコンテキストがwindowオブジェクトです。そこで、letとconst以外で宣言したグローバル変数と関数はwindowオブジェクトのプロパティとメソッドになるわけです。
###コンテキストスタック(context stack)
すべての関数呼び出しには独自のコンテキストが存在する。プログラムの実行が関数の中に入った時、該当関数のコンテキストがコンテキストスタックの中にpushされる。関数の実行が終わったら該当関数のコンテキストがコンテキストスタックからpopされる。これによってプログラムのコントロール権が一個前のコンテキストに移動する。よって今現在プログラムのコントロール権を持っているのはコンテキストスタックへ最後にpushされたコンテキストです。
上記で見たの通り、JavaScriptプログラムの実行の流れがこのコンテキストスタックによって制御されている。
###スコープチェーン(scope chain)
コンテキストのプログラムが実行する際変数オブジェクトの「スコープチェーン」を構築する、このスコープチェーンによって各コンテキストのプログラムがアクセスする変数や関数の順番を決める。今実行中のコンテキストの変数オブジェクトが常にスコープチェーンの先頭にあります。
グローバル変数オブジェクトが常にスコープチェーンの最後にあります。
コンテキストのプログラムを実行する時、利用する変数や関数をこのスコープチェーンの先頭から最後のグローバル変数オブジェクトまで検索していきます、見つけたらそこで終了、見つけられなかったらエラーになる。
var globalVar = "global";
function outterFunc(){
let outVar = "outterFunc";
function innerFunc(){
let innerVar = "innerFunc";
console.log(globalVar); //アクセスできる
console.log(outVar); //アクセスできる
console.log(innerVar); //アクセスできる
}
innerFunc();
console.log(globalVar); //アクセスできる
console.log(outVar); //アクセスできる
console.log(innerVar); //アクセスできない
}
outterFunc();
console.log(globalVar); //アクセスできる
console.log(outVar); //アクセスできない
console.log(innerVar); //アクセスできない
図でみるとこんな感じです
矢印のように内部のコンテキストはスコープチェーンを使って外部コンテキストの変数や関数を検索してアクセスする、逆の外部から内部をアクセスすることはできない。
####「catch」と「with」におけるスコープチェーン
実行コンテキストは主にグローバルコンテキストと関数コンテキストの二種類です。
だが「try/catchのcatchブロック」と「with」の場合はスコープチェーンの先頭に一時的なコンテキストを追加する。