ES 6イベントサイクル機構

7939 ワード

実行コンテキスト(Execution Cotext)
JavaScriptの中の運行環境は大体3つの状況が含まれています.
  • グローバル環境:JavaScriptコードが実行されると、まずこの環境に入ります.
  • 関数環境:関数が実行されると、現在の関数で実行コード
  • に入ります.
  • eval:セキュリティ上の問題があります.(それは文字列に伝達された任意の文字列を実行することができますので、文字列や素性が不明で、信頼されていないソースのパラメータに永遠に入らないでください.)使用を推奨しません.無視できます.
  • コントローラが実行可能なコードに移るたびに、実行コンテキストに入ります.実行コンテキストは、現在のコードの実行環境として理解され、作用領域が形成されます.
    関数コールスタック(call stack)
    したがって、JavaScriptプログラムでは、必ず複数の実行コンテキストが生成され、JavaScriptエンジンは、関数としてスタックを呼び出す方法でそれらを処理します.スタックの底は常にグローバルコンテキストであり、スタックトップは現在実行中のコンテキストである.
    var color = 'blue';
    
    function changeColor() {
        var anotherColor = 'red';
    
        function swapColors() {
            var tempColor = anotherColor;
            anotherColor = color;
            color = tempColor;
        }
    
        swapColors();
    }
    changeColor();
    
    注意:関数では、実行可能なコードの実行は、returnによって直接終了することができます.したがって、現在のコンテキストは、スタックをポップアップします.
    グローバルコンテキストのライフサイクルは、プログラムのライフサイクルと一致しています.ブラウザウィンドウをオフにするなど、プログラムの実行が終了しない限り、グローバルコンテキストは常に存在します.その他のすべてのコンテキスト環境は、グローバルコンテキストの属性に直接アクセスできます.
    このプロセスを解いたら、実行文脈についてまとめられます.
  • 単スレッド
  • 同期実行は、スタックトップのコンテキストだけが実行中であり、他のコンテキストは
  • を待つ必要がある.
  • グローバルコンテキストは唯一のもので、ブラウザが閉じているときにスタック
  • を出す.
  • 関数の実行文脈の個数は制限されていません.
  • は、ある関数が呼び出されるたびに、呼び出しの自己関数
  • であっても、新しい実行コンテキストを作成します.
    コンテキストライフサイクルを実行
    一つの実行コンテキストのライフサイクルは、二つの段階に分けられます.
  • 作成段階:この段階では、実行コンテキストは、それぞれ変数オブジェクトを作成し、スコープチェーンを確立し、thisの指向性を決定する.
  • 変数オブジェクトを作成します.
  • は、argmentsオブジェクトを確立する.現在のコンテキストのパラメータを確認し、オブジェクトの下の属性と属性値を設定する.
  • は、現在のコンテキストの関数宣言をチェックします.変数オブジェクトに関数名で属性を作成します.属性値は、関数の存在するメモリアドレスに対する参照です.関数名の属性が既に存在する場合、この属性は新しい参照によって上書きされます.
  • は、現在のコンテキストにおける変数宣言をチェックします.変数オブジェクトに変数名で属性を作成し、属性値はundefinedであり、変数名の属性が既に存在する場合、同じ名前の関数がundefinedに変更されないように直接スキップします.元の属性値は変更されません.
  • は、現在の環境と上位環境との一連の変数オブジェクトから構成されたアクティブドメインチェーンを確立し、アクセス権限に適合する変数と関数に対する現在の実行環境の規則的なアクセスを保証する.
  • は、thisの指向を決定しました.関数が呼び出されたときに決定されました.関数実行中に、thisが決定されると、変更できなくなります.使用者関数があるオブジェクトによって所有されている場合、その関数は呼び出し時に内部のthisがオブジェクトを指します.関数が独立して呼び出されると、関数内部のthisはundefinedを指します.
  • コードの実行フェーズ:作成が完了すると、コードの実行が開始されます.このとき、変数の割り当て、関数の参照、その他のコードの実行が完了します.
  • 変数オブジェクトを作成:
    例1:
    function test() {
        console.log(a);
        console.log(foo());
    
        var a = 1;
        function foo() {
            return 2;
        }
    }
    test();
    
    に等しい
    function test() {
        function foo() {
            return 2;
        }
        var a;
        console.log(a);
        console.log(foo());
        a = 1;
    }
    
    test();
    
    例2:
    function test() {
        console.log(foo);
        console.log(bar);
    
        var foo = 'Hello';
        console.log(foo);
        var bar = function () {
            return 'world';
        }
    
        function foo() {
            return 'hello';
        }
    }
    
    test();
    
    に等しい
    function test() {
        function foo() {
            return 'hello';
        }
        var bar;
    
        console.log(foo);
        console.log(bar);
        foo = 'Hello';
        console.log(foo);
        var bar = function () {
            return 'world';
        }
    }
    
    test();
    
    実行フェーズに入っていないと、変数オブジェクトの属性はアクセスできません.しかし、実行段階に入ると変数オブジェクトがアクティブオブジェクトに変わり、中の属性がアクセスされ、実行段階の操作が開始されます.変数オブジェクトとアクティブオブジェクトは同じオブジェクトです.コンテキストを実行する異なるライフサイクルです.ただし、スタックトップを呼び出す関数の実行コンテキストにある変数オブジェクトだけがアクティブオブジェクトになります.変数オブジェクトを作成して変数の昇格を理解することができます.
    作用ドメインチェーンを確立する:作用ドメインチェーンは、現在の環境と上位環境の一連の変数オブジェクトから構成されており、現在の実行環境がアクセス権限に適合する変数と関数に対して規則的にアクセスすることを保証しています.
    var a = 20;
    
    function test() {
        var b = a + 10;
    
        function innerTest() {
            var c = 10;
            return b + c;
        }
    
        return innerTest();
    }
    
    test();
    
    thisの指向を決定します.thisの指向は、関数が呼び出されたときに決定されます.関数実行中に、thisが決定されると、変更できなくなります.使用者関数があるオブジェクトによって所有されている場合、その関数は呼び出し時に内部のthisがオブジェクトを指します.関数が独立して呼び出されると、関数内部のthisはundefinedを指します.
    // demo01
    var a = 20;
    function fn() {
        console.log(this.a);
    }
    fn();
    
    // demo02
    var a = 20;
    function fn() {
        function foo() {
            console.log(this.a);
        }
        foo();
    }
    fn();
    
    // demo03
    var a = 20;
    var obj = {
        a: 10,
        c: this.a + 20,
        fn: function () {
            return this.a;
        }
    }
    
    console.log(obj.c);
    console.log(obj.fn());
    
    callを使って、appyは指定されたthisを表示します.
    function fn() {
        console.log(this.a);
    }
    var obj = {
        a: 20
    }
    
    fn.call(obj);
    
    callとappyの後ろのパラメータは、実行する関数にパラメータを渡すものです.callは1つの形で伝達され、appyは配列として伝達される.これは彼らの唯一の違いです.
    function fn(num1, num2) {
        console.log(this.a + num1 + num2);
    }
    var obj = {
        a: 20
    }
    
    fn.call(obj, 100, 10); 
    fn.apply(obj, [20, 10]); 
    
    イベントサイクル機構
    JSエンジンは単スレッドイベントサイクルの概念上に確立されている.シングルスレッド(Single-threaded)は、同じ時刻にコードの一部しか実行できないことを意味し、Swift、JavaまたはC+というように、複数の異なるコードを同時に実行できるマルチスレッド言語とのギャップを形成している.
    JavaScriptコードの実行中は、関数コールスタックによって関数の実行順序を解決する以外に、タスクキュー(task queue)によって他のコードの実行を解決します.
  • スレッドでは、イベントサイクルは唯一であるが、ジョブキューは複数あり得る.
  • タスクキューはまた、macro-task(マクロタスク)とmicro-task(マイクロタスク)に分けられ、最新の基準では、taskとjobsと呼ばれる.
  • macro-taskは、概ねscript(全体コード)、setTimeout、set Interval、set Immedite、I/O、UI rendengを含む.
  • micro-taskは、process.nextTick、Promise、Object.observe(廃棄)、MuttionObserver(html 5新特性)
  • を大まかに含む.
  • setTimeout/Promiseなどをミッションソースと呼びます.タスクの列に入るのは、彼らが指定した具体的な実行タスクです.
  • 異なるタスクソースからのタスクは、異なるタスクキューに入る.
  • イベントサイクルの順序は、JavaScriptコードの実行順序を決定する.それはscript(全体コード)から初めて循環します.その後、グローバルコンテキストは関数コールスタックに入ります.スタックがクリアされるまで(全体の部分のみ)、すべてのmicro-taskを実行します.すべての実行可能なmicro-taskが実行された後.サイクルは再びmacro-taskから始まり、その中の一つのタスクキューを見つけて実行しました.そして、すべてのmicro-taskを実行して、このようにずっと循環していきます.
  • の各タスクの実行は、macro-taskであろうと、micro-taskであろうと、関数によってスタックを呼び出して行われる.
  • 例1:
    setTimeout(function() {
        console.log('timeout1');
    })
    
    new Promise(function(resolve) {
        console.log('promise1');
        for(var i = 0; i < 1000; i++) {
            i == 99 && resolve();
        }
        console.log('promise2');
    }).then(function() {
        console.log('then1');
    })
    
    console.log('global1');
    
    例2:
    // demo02
    console.log('glob1');
    
    setTimeout(function() {
        console.log('timeout1');
        process.nextTick(function() {
            console.log('timeout1_nextTick');
        })
        new Promise(function(resolve) {
            console.log('timeout1_promise');
            resolve();
        }).then(function() {
            console.log('timeout1_then')
        })
    })
    
    setImmediate(function() {
        console.log('immediate1');
        process.nextTick(function() {
            console.log('immediate1_nextTick');
        })
        new Promise(function(resolve) {
            console.log('immediate1_promise');
            resolve();
        }).then(function() {
            console.log('immediate1_then')
        })
    })
    
    process.nextTick(function() {
        console.log('glob1_nextTick');
    })
    new Promise(function(resolve) {
        console.log('glob1_promise');
        resolve();
    }).then(function() {
        console.log('glob1_then')
    })
    
    setTimeout(function() {
        console.log('timeout2');
        process.nextTick(function() {
            console.log('timeout2_nextTick');
        })
        new Promise(function(resolve) {
            console.log('timeout2_promise');
            resolve();
        }).then(function() {
            console.log('timeout2_then')
        })
    })
    
    process.nextTick(function() {
        console.log('glob2_nextTick');
    })
    new Promise(function(resolve) {
        console.log('glob2_promise');
        resolve();
    }).then(function() {
        console.log('glob2_then')
    })
    
    setImmediate(function() {
        console.log('immediate2');
        process.nextTick(function() {
            console.log('immediate2_nextTick');
        })
        new Promise(function(resolve) {
            console.log('immediate2_promise');
            resolve();
        }).then(function() {
            console.log('immediate2_then')
        })
    })
    
    80%の応募者が不合格となったJSの面接問題
    Excuse me?この先は面接です.
    https://yangbo5207.github.io/wutongluo/