JS-Flow]JavaScriptを実行するコンテキスト(Execution Context)



この文章はCore JavaScript特別講座の内容をまとめた.

0.実行コンテキストとは?


実行するコードで提供される環境情報をまとめたオブジェクトは、同じコードを実行するときに必要な環境情報を収集してコンテキストを整理し、呼び出しスタックに積み上げて実行順序を保証します.
javascriptでは、コンテキストを実行する単位(コードパッケージ)が関数です.
JAvascriptは、コード実行に必要な環境情報を含むオブジェクト、すなわち実行コンテキストを関数単位で組織および利用します.
グローバルスペースも関数です.
javascriptファイルを実行すると、グローバルスペースが実行され、グローバルスペースの終了時に実行が終了します.
グローバル空間も関数のように実行と終了の概念であるため、グローバル空間も関数である.

1.コールスタック


callスタックとは、現在どの関数が実行されているか、次の関数が呼び出されるべきかなどを制御するデータ構造です.
次のコードがcallスタックにどのように積み重ねられているかを見てみましょう.

サンプルコード

var a = 1;
function outer() {
    console.log(a);
    
    function inner() {
        console.log(a);
        var a = 3;
    }
    
    inner();
    
    console.log(a);
}
outer();
console.log()

まず、グローバル空間のグローバルコンテキストがcallスタックにスタックされます.その後、outer()関数の実行コンテキストに対して累積し、outer()関数のうちinner関数の実行コンテキストに対して累積する.

2.実行コンテキスト内の3つのオブジェクト


1つの実行コンテキストは、次の構造で構成されます.
- 실행컨텍스트
	- VariavleEnvironment
		- environmentRecord(snapshot)
		- outerEnvironmentReference(snapshot)
	- Lexical Environment
		- environmentRecord : 현재문맥의 식별자(hoisting)
		- outerEnvironmentReference : 외부 식별자(scope chain)
	- ThisBinding
スタックを呼び出すときに使用するコードの実行コンテキスト構造を下図に示します.
inner()関数の実行コンテキストのみならずouter()전역 컨텍스트も同様の構成である.
ただし、전역 컨텍스트外部環境参照なし.グローバルコンテキストは最も外部なので、外部参照はありません.

2.1. Variable Environment


現在のコンテキストの識別子情報、外部環境情報、宣言時点のスナップショット/457914、およびスナップショットを維持します.LexicalEnvironmentVariable Environment構造的には同じであり、初期には同じ情報が含まれている.ただし、コードの進行に伴い、Lexical Environment値が変更されます.
したがって、知っていればLexical EnvironmentLexical Environmentということも自然に理解できる.
これを覚えておきましょう.Variable EnvironmentVariable Environmentの初期情報のみを含む(snapshot).

2.2. Lexical Environment

Lexical Environment再度2種類に分けて作業を行う.

2.2.1. environmentRecord


現在のコンテキストの識別子情報を収集し、環境レコードに格納します.このような行為をHostingと呼ぶ.
識別子は、簡単に言えば変数名、関数名、パラメータ名などである.
では、ホスティングは何ですか.
シースは、識別子情報を実行コンテキストの上部にドラッグします.簡単な例で説明しましょう.
  • サンプルコード
  • console.log(a());
    console.log(b());
    console.log(c());
    
    function a() {
        return 'a';
    }
    var b = function bb() {
        return 'b';
    }
    var c = function cc() {
        return 'c';
    }
  • 護衛結果
  • function a() {
        return 'a';
    }
    var b;
    var c
    console.log(a());
    console.log(b());
    console.log(c());
    
    b = function bb() {
        return 'b';
    }
    c = function cc() {
        return 'c';
    }
    実際には、コードはこのように変更されていません.これは,符号化の仕方を概念的に説明するために作成されたものであるが,概念とコードが一致しているため,このように理解しても問題ない.
  • environmentRecord
  • {
        function a() {...},
        b,
        c,  
    }
    EnvironmentRecordのアクション(反発)の結果、EnvironmentRecordオブジェクトには現在のコンテキストの識別子情報が含まれます.Lexical Environmentletスタンドにもなります.
    ただconstのように、価格に近づけないので、お得感がなさそうです.
    従って、varletも環境記録においてハイライトとなる.
    注意:letとconstは選択されますか?

    2.2.2. outerEnvironmentReference


    現在のコンテキスト(実行コンテキスト)に関連する外部(実行コンテキスト外部)識別子情報を収集します.
    スコプフとは、識別者に対する有効範囲を指す.JAvascriptには関数スキャンとブロックスキャンがほぼ存在し,これらのスキャンを内向外から順に検索することをスキャンチェーンと呼ぶ.そして、それを可能にしたのはconstの2番目の収集資料LexicalEnvironment最初に見た例に戻り、outerEnvironmentReferenceで外部識別子情報を参照する方法を確認します.

    外部コンテキストの内部コンテキストは内部コンテキストであり、外部コンテキストはグローバルコンテキストである.したがって、外部()コンテキストはグローバルコンテキストを参照でき、内部()コンテキストは参照できません.
    これにより,中から値がなければ,外に値を探すことでスキャンチェーンを実現できる.

    3.関数の実行時(コンテキストがアクティブな場合)の動作

  • 該当するコンテキストを生成する.
  • 収集環境記録(変数宣言、関数宣言)
  • 逐行符号化
  • 識別子の値が必要な場合は、自分のコンテキストの環境記録を探索する.
  • ない場合は、OuterEnvirenmentReferenceを使用して、前のレベルのコンテキスト内を移動(ターゲット識別子が見つかるまで&&グローバルコンテキスト)