次のような私たちはすべての実行JSコードの順序は、常にコードの順序とは異なります、あなたはそれさえも、同期符号ができますヘッドはさておき、非同期の問題は、その実行はまた、あなたの期待と矛盾していることを知って、
関数F1(){ にconsole.log( '風風を聞く' ); }; F1(); // エコー 関数F1(){ にconsole.log( 'エコー' ); }; F1(); // エコー
コード書かれた順序に従って、最初の風を聞くべき出力は風であり、そして、出力エコー魚は、残念ながら、2つの出力はエコーされ、我々は、上記のコード変更機能発現の関数を宣言した場合、結果は同じではありません。
VaRの F1 = 関数(){ にconsole.log( '風風を聞く' ); }; F1(); // 風が風である聞く するvar F1 = 関数(){ にconsole.log( 'エコー' ); }; F1 (); // エコー
コードが実行前に、いくつかの微妙な変化が起こっていなければならないことをこの番組では、JSエンジンは、実際には全く何もして?これは、JSの実行コンテキストを言及する必要があります。
JSの実行コンテキスト
JSコード実行の前に、JSエンジンは、常にいくつかの準備作業は、実際には、ジョブは、対応する実行コンテキストを作成することですか。
実行コンテキストとのみ三つのカテゴリー、グローバル実行コンテキスト、関数コンテキスト、およびevalのコンテキスト ; evalは、一般的に使用によるものではない、ここでは説明しません。
1.グローバル実行コンテキスト
唯一のグローバル実行コンテキスト、クライアントは一般的にブラウザによって作成され、ウィンドウオブジェクトを知られている、我々はこのを通してそれに直接アクセスすることができます。
事前に定義されたメソッドとプロパティの数に関するグローバルオブジェクトウィンドウ、我々は直接、地球環境に任意のプロパティでこれらのメソッドにアクセスすることができますサポートグローバル変数ウィンドウオブジェクトまたはvarステートメントながら。グローバルオブジェクトによって作成された私たちvarが、窓から直接アクセスすることができます。
2.機能の実行コンテキスト
関数の実行コンテキストが多数存在することができ、関数が呼び出されるたびに関数コンテキストを作成し、同じ機能を呼び出すことによって作成されます。なお、新たなコンテキストを。
あなたが文脈の異なったタイプをお勧めします、その数はまだ彼らがどのように関係を作ることがたくさんですが、また、誰が話をしていたことの文脈、管理しようとしていることを言って、実行コンテキストスタックアップを。
実行コンテキストスタック(実行スタック)
また、コール・スタックとして知られている実行コンテキストスタック(以下、略称実行スタック)は、実行コード中に実行スタック用に作成されたすべてのコンテキストが格納されている、のLIFO特性を有する(リア高度最後にファーストアウト)。
JSコード最初のランは、あろうグローバル実行コンテキストを作成し、実行スタックに押し込ま関数が呼び出されるたびに、その後、スタック内の新しい機能の実行コンテキストと圧力が作成され、;による実行スタックLIFOの特性、
実行JSコードが終了する前に、それは、スタックの一番下にある、として理解することができます永遠にグローバル実行コンテキストを持っています。
関数F1(){ F2()。 console.log( 1 )。 }。 関数F2(){ F3()。 console.log( 2 )。 }。 関数F3(){ にconsole.log( 3 )。 }。 F1(); // 3 2 1
私たちは、理解を容易にするために、スタックの間および上記のプロセスの実行コンテキストのコードを実行することによって関係を説明配列され、我々は実行スタックの錯覚を持っているコードの最初の実行では、スタックにグローバル実行コンテキストを作成すると、次のようにので、プロセスは次のとおりです。
// コードがグローバル実行コンテキストを作成するために実行される前 ECStack = [GlobalContext]。
// F1コール ECStack.push( 'F1 functionContext' );
// f1とf2の呼び出し実行は1コンソールことができない前に、f2が完了し ECStack.push(「F2 functionContext」を)。
// f3が終了する前に、F2は2コンソールすることができ、F3と呼ばれている ECStack.push( 'F3 functionContextを' );
// F3は、スタック3の出力終了する ECStack.pop();
// F2は、スタック2の出力終了する ECStack.pop();
// F1は、出力1とスタック終了する ECStack.pop();
// この時点で、唯一つの実行スタックのグローバル実行コンテキスト
そこでここでは、実行スタックや店舗の実行コンテキストのルールを説明し;、JSエンジンは実行コンテキストを作成することができる状態になります前に、私の前の上記のコードが実行される覚えて、具体的にそれを作成する方法を、私たちが言うようになりました。
実行コンテキスト作成フェーズ
分割実行コンテキストの作成作成段階と実施段階2つの段階を、理解するのがより難しいが、作成段階である必要があり、我々は、作成フェーズで始まります。
JS実行コンテキスト作成フェーズは、三つのことを担当します。
これを決定する1
字句環境を作成します。2.(LexicalEnvironment)
変数環境(VariableEnvironment)を作成します3。
ここで私はちょうど他の人から学ぶ作成プロセスを表現するために、擬似コードデータを翻訳:
=のExecutionContext { // この値決定 ThisBinding = < この値は> 、 // 字句環境を作成する LexicalEnvironment = {}、 // 変数環境を作成 VariableEnvironmentを= {}、 }。
あなたはこの質問を読んでいる必要があります実行コンテキストについての他の記事を読んだことがある場合は、作成プロセスの実行コンテキストは、この、アクティブなオブジェクトの魚が行う変数オブジェクト/の範囲を説明するべきではありません、これは同じではないと他の場所を言うために、どのように私は後で説明します。
これを決定する1
このバインディング、グローバル実行コンテキストの公式コールが、これは常に、このようなブラウザ環境として、グローバルオブジェクトにwindowオブジェクトにこの点を指摘します。
関数の実装のコンテキストでは、この関数の値に応じて、オブジェクトが呼び出された場合、これはオブジェクトを指す、と呼ばれています。そうでない場合、これは一般にグローバル・オブジェクト・ウィンドウ又は不定(strictモード)を指します。
2.字句環境
ここで、可変マッピング構成識別子を含む字句環境は、識別子が示す変数/関数の名前は、変数が実際のオブジェクト含むの関数であり、[]タイプのオブジェクトまたは元の値を参照します。(それは読み取ることはできません)
字句環境地球レキシカル環境と機能字句環境 2種類
グローバル字句環境:
それは環境自体の最外層であり、外部環境のレコードを導入することは、それが含まれていることを除いて、nullであるすべてのグローバルオブジェクトのメソッドの特性、及び(varで宣言された)グローバルオブジェクトをユーザ定義します。
レキシカル関数の環境:
これは、ユーザー定義関数内のすべての変数を、だけでなく、含まれる引数オブジェクトを。レキシカル関数の環境外部環境が地球環境に導入することができる、環境が他の機能もあり、これは実際のコードが来るに従って、。
// 地球環境 GlobalExectionContext = { // グローバル語彙環境 LexicalEnvironment:{ // 環境レコード EnvironmentRecord:{ タイプ:「オブジェクト」、// オブジェクト環境レコードのタイプ // ここ結合識別子 }、 アウター: < NULL > } }; // 周囲の関数 FunctionExectionContext = { // 関数字句環境 LexicalEnvironment:{ // 環境レコード EnvironmentRecord:{ タイプ: "宣言"は、// 宣言環境レコードを入力します // ここでは結合識別子 }、 表地: <参加無料またはouterfunction環境リファレンス> } };
3.環境変数
環境変数も、字句環境は、それはレキシカル環境のすべての属性を持っていると言うことができるような環境のレコードの導入や外部環境を持っています、。ES6のための字句環境でのみ差嘘変数ストレージとは、constの関数宣言文を聞かせて、環境変数varに格納された変数は、単に宣言しました。
私たちは、擬似コードの束によってそれらを理解する必要があります。
= 20ましょう。 CONST B = 30 。 VaRのC; 関数は、乗算(E、F){ VAR G = 20 。 リターン E * F * グラム。 } C =乗算(20、30)。
私たちは、上記のコードの実行コンテキストを作成するプロセスを説明する擬似コード:
= 20ましょう。 CONST B = 30 。 VaRのC; 関数は、乗算(E、F){ VAR G = 20 。 リターン E * F * グラム。 } C =乗算(20、30)。
私たちは、上記のコードの実行コンテキストを作成するプロセスを説明する擬似コード:
// グローバル実行コンテキスト GlobalExectionContext = { // にバインドされたこのグローバルオブジェクト ThisBinding:<オブジェクト参加無料> 、 // 字句環境 LexicalEnvironment:{ // 環境を録音 EnvironmentRecord:{ タイプ:「オブジェクト」、 // オブジェクト環境を録音 @ でAB CONSTてみましょうここで作成した変数識別子バインディング <初期化されていない>: 、 :B <初期化されていない> 、 乗算: <FUNC> } // 地球環境、外部環境がヌルとして導入され 、外側:< ヌル >を }、 VariableEnvironment:{ EnvironmentRecord:{ タイプ:「オブジェクト」、 // オブジェクト環境レコード // 識別子この中で、ここで作成したCのVAR結合 はC:未定義、 } // 外部環境がnullとして導入された地球環境 外に:< ヌル > } }
// 関数の実行コンテキスト FunctionExectionContext = { // この関数は、グローバルオブジェクトをデフォルトのバインディングによって呼び出されるためでもある <株式会社参加無料オブジェクト>:ThisBinding 、 // 字句環境 LexicalEnvironment:{ EnvironmentRecord:{ タイプ:「宣言」、 // 宣言型環境記録 // 識別子結合引数ここでオブジェクトその 引数:{0:2:30、長さ:20 ,. 1である} } // 外部環境がレコード内に導入される</参加無料> 外<GlobalEnvironment> } VariableEnvironment :{ EnvironmentRecord:{ タイプ: "宣言"、 //宣言型環境レコード // 識別子結合varは、このグラムで、ここで作成された G:未定義 }、 // 外部環境は、レコード内に導入される</参加無料> 外を<GlobalEnvironment> } }
私は、あなたが発見していない知っている、実行コンテキストでのステージを作成し、VARを持つ変数関数の宣言は、作成段階で宣言されていないが、与えられた値、varステートメントはundefinedに設定され、関数は、独自の機能のために設定されてやる、とCONSTに設定されてみましょう未初期化。
今、あなたは常に、それはそれだった、そしてなぜ範囲は初期化フェーズJSエンジンの異なる割り当ての両方のために作成されているため、一時的なデッドゾーンを持っているのconstなぜ聞かせてどのように事前に関数宣言を強化するための変数を知っています。
対応するコードは、このようなVARの作成の初期段階として割り当て、前の環境の記録に基づいて実行された場合、ステージの文脈だけでなく、私たちはより良い理解すべきで実装フェーズを、作成に加えて、のようなconstの値を聞かせて割り当てられ、対応する値がある場合は、定義されていません値が割り当てられている場合、初期化されていないが、何の値が未定義に与えられていません。
概要
1.グローバル実行コンテキストは、一般的に、それがコードの実行を作成するブラウザによって作成され、実行コンテキストは、関数呼び出しのコンテキストが作成された回数をどのように多くの関数が呼び出される機能のみを、作成されます。
2.コールスタックはFILOルールを満たすために、すべての実行コンテキストを格納するために使用されます。
3.ドゥコンテキスト確立フェーズは、この結合に分割して、字句の環境を作成し、環境変数の三段階では、2つの違いは、レキシカル環境変数がconstのlet文と関数宣言を格納しますが、唯一の変数、環境変数var宣言を格納するということです。
4.環境レコード2つの語彙部分は、主に、記録環境となる外部環境、グローバルコンテキストによって導入され、そして外部環境を導入するコンテキスト機能が同じレコード、グローバルnullでない、機能は、地球環境又は他の環境の関数です。環境記録は、宣言型環境レコードと呼ばれる、オブジェクト、関数と呼ばれる総合的な環境のレコード、同じではありません。
5.あなたは、可変リフト、改善された機能がある理由を理解する必要がありますが、constのを聞かせていませんでした。
ES5後6.ES3変数オブジェクトとアクティブオブジェクトはレキシカル環境によって説明する前に、コンセプト、環境変数、2は、よりユーザーフレンドリーな理解であるという概念、と競合しません。