定義から実行まで、JSエンジンは実装レイヤーで多くの初期化作業を行います。したがって、JSエンジンの作業メカニズムを学習する前に、実行環境スタック、グローバルオブジェクト、実行環境、可変オブジェクト、アクティブオブジェクト、スコープチェーン、スコープチェーンなど、いくつかの関連する概念を導入する必要があります。これらの概念は、JSエンジンの作業のコアコンポーネントです。この記事の目的は、各概念を単独で説明するのではなく、単純なデモを介してそれを分析し、定義から実行までのJSエンジンの詳細と、これらの概念が果たす役割を説明することです。
var x = 1; //グローバル変数XFunction a(y){var x = 2;を定義します。 //ローカル変数x関数B(z)を定義する{//内部関数b console.log(x+y+z)を定義します。 } burten b; //関数b} var c = a(1)への参照を返します。 // aを実行し、bc(1)を返します。 //関数を実行するbこのデモは閉鎖であり、実行の結果は4です。以下では、3つの段階でJSエンジンの作業メカニズムを分析します。グローバル初期化、実行機能A、および実行関数B :
1。グローバル初期化
JSエンジンが実行可能なコードに入るとき、次の3つの初期化タスクを完了する必要があります。
まず、グローバルオブジェクト(グローバルオブジェクト)を作成します。このオブジェクトにはグローバルコピーが1つしかなく、そのプロパティはどこでもアクセスでき、その存在はアプリケーションのライフサイクル全体に付随します。グローバルオブジェクトを作成する場合、数学、文字列、日付、ドキュメントなどのJSオブジェクトが一般的に使用されます。このグローバルオブジェクトには名前で直接アクセスできないため、別のプロパティウィンドウがあり、ウィンドウ自体を指しているため、グローバルオブジェクトにウィンドウを介してアクセスできます。擬似コードを使用してグローバルオブジェクトをシミュレートする一般的な構造は次のとおりです。
//グローバルオブジェクトの作成var globalObject = {math:{}、string:{}、date:{}、document:{}、// dom operation ... window:this //ウィンドウ属性がそれ自体をポイントにする}次に、JSエンジンは実行コンテキストスタックを構築する必要があります。同時に、グローバル実行コンテキストECを作成し、このグローバルな実行環境ECを実行環境スタックに押し込む必要があります。実行環境スタックの機能は、プログラムを正しい順序で実行できるようにすることです。 JavaScriptでは、各関数には独自の実行環境があります。関数を実行すると、関数の実行環境が実行環境スタックのトップに押し込まれ、実行権が取得されます。この関数が実行されると、その実行環境はスタックの上部から削除され、実行右は以前の実行環境に返されます。 pseudocodeを使用して、実行環境スタックとECの関係をシミュレートします。
var ecstack = []; //アレイvar ec = {}と同様に、実行環境スタックを定義します。 //実行スペースを作成します。 //関数を入力し、実行環境ECSTACK.POP(EC)をプッシュします。 //関数が戻った後、実行環境を削除します最後に、JSエンジンは、ECに関連付けられたグローバル変数オブジェクト(Varibaleオブジェクト)VOを作成し、グローバルオブジェクトにポイントvoを作成します。 VOには、グローバルオブジェクトの元のプロパティが含まれているだけでなく、変数xと機能Aがグローバルで定義されていることも含まれています。同時に、関数Aを定義する場合、内部属性スコープもAに追加され、ポイントスコープがVOに追加されます。各関数が定義されると、それに関連付けられたスコープ属性が作成され、スコープは常に関数が定義されている環境を指します。この時点でのecstack構造は次のとおりです。
ecstack = [//実行環境スタックEC(g)= {//グローバル実行環境vo(g):{//グローバル変数オブジェクト... //グローバルオブジェクトの元の属性を含むx = 1; //変数x a = function(){...}を定義します。 //関数aa [[scope]] = this; // aのスコープを定義し、VO自体に値を割り当てます}}];2。機能aを実行します
実行がa(1)に入ると、JSエンジンは次のことを行う必要があります。
まず、JSエンジンは機能Aの実行環境ECを作成し、ECは実行環境スタックの最上部にプッシュし、実行権を取得します。現時点では、実行環境スタックには2つの実行環境、つまりグローバル実行環境と機能A実行環境があります。 Aの実行環境はスタックの上部にあり、グローバル実行環境はスタックの下部にあります。次に、機能のスコープチェーンAを作成します。JavaScriptでは、各実行環境には識別子解像度のための独自のスコープチェーンがあります。実行環境が作成されると、そのスコープチェーンは、現在実行されている機能の範囲に含まれるオブジェクトとして初期化されます。
次に、JSエンジンは、現在の関数のアクティブオブジェクト(アクティベーションオブジェクト)AOを作成します。ここでのアクティブオブジェクトは可変オブジェクトの役割を再生しますが、関数では異なって呼ばれます(変数オブジェクトは一般的な概念であり、アクティブオブジェクトはその分岐であると考えることができます)。 AOには、関数の正式なパラメーター、引数オブジェクト、このオブジェクト、およびローカル変数と内部関数の定義が含まれており、AOはスコープチェーンの最上部にプッシュされます。関数Bを定義する場合、JSエンジンは、関数Bが定義されている環境にBにスコープ属性を追加し、ポイントスコープを追加することに注意してください。関数Bが定義されている環境はAのアクティブオブジェクトAOであり、AOはリンクリストのフロントエンドにあります。リンクリストにはエンド接続の特性があるため、関数Bの範囲はAのスコープチェーン全体を指します。
ecstack = [//実行環境スタックEC(a)= {// aの実行環境[スコープ]:vo(g)、// voはグローバル変数オブジェクトao(a):{//アクティブオブジェクトy:1、x:2、//ローカル変数x b:function(){...}を定義します。 //これはAO自体を参照し、AOはScopechainの上部にあるため、B [[scope]]がスコープチェーン引数全体を指します:[]、//関数でアクセスする引数は、window this:window //これは発信者ウィンドウオブジェクトを指します}、scopechain:<ao(a)、a scopech]次に、AOがスコープチェーンの上部に追加されます。この時点で、aのスコープチェーン:ao(a) - > vo(g)}、ec(g)= {//グローバル実行環境vo(g):{//グローバル変数オブジェクトの作成... //グローバルオブジェクトの元の属性を含むx = 1; //変数x a = function(){...}を定義します。 //関数aa [[scope]] = thisを定義します。 // a、a [[scope]] == vo(g)}}の範囲を定義します。3。機能bを実行します
関数Aが実行された後、bへの参照が返され、変数Cに割り当てられます。C(1)の実行はB(1)の実行に相当します。 JSエンジンは、次のタスクを完了する必要があります。
まず、上記のように、関数Bの実行環境ECを作成し、ECを実行環境スタックの最上部に押し込み、実行権を取得します。現時点では、実行環境スタックには2つの実行環境、つまりグローバル実行環境と機能Bの実行環境があります。Bの実行環境はスタックの最上部にあり、グローバル実行環境はスタックの下部にあります。 (注:関数Aが戻ると、Aの実行環境はスタックから削除され、グローバル実行環境のみを残します)次に、関数Bのスコープチェーンを作成し、機能Bの範囲に含まれるオブジェクトに初期化します。つまり、関数BのアクティブオブジェクトAOを作成し、パラメーターz、このオブジェクトを使用します。この時点で、Ecstackは次のようになります。
ecstack = [//実行環境スタックEC(b)= {// bの実行環境を作成し、スコープチェーンの上部にあります[スコープ]:ao(a)、//関数のスコープチェーンA、ao(a) - > vo(g)var ao(b)= {//アクティブオブジェクトのアクティブなオブジェクトを作成しますb z:1、windowments: scopechain:<ao(b)、b [[scope]]> //リンクリストはb [[scope]]に初期化され、その後、ao(b)がリンクリストのヘッダーに追加されます。この時点で、Bのスコープチェーン:ao(b) - > ao(a)-vo(g)}、ec(a)、// aの実行環境はスタックの上部から削除されています。ec(g)= {//グローバル実行環境Vo:{//グローバルオブジェクトx = 1の元の属性を含むグローバル属性x = 1; //変数x a = function(){...}を定義します。 //関数aa [[scope]] = this; // aのスコープを定義します。関数bが「x+y+z」を実行する場合、3つの識別子x、y、zを1つずつ解析する必要があります。解析プロセスは、変数検索ルールに準拠しています。最初に、アクティブオブジェクトに属性が存在するかどうかを見つけます。それが存在する場合は、検索を停止して戻ります。存在しない場合は、範囲チェーンに沿って上部から検索し続けます。変数がスコープチェーン全体で見つからない場合は、「未定義」を返します。上記の分析から、機能Bの範囲チェーンが次のとおりであることがわかります。
ao(b) - > ao(a) - > vo(g)
したがって、変数xはAO(a)に見られ、VO(g)でxを探しません。変数yはAO(a)にあり、変数zは独自のAO(b)に見られます。したがって、実行結果: 2+1+1 = 4。
簡単な要約
JSエンジンの作業メカニズムを理解した後、概念を理解するレベルにとどまることはできませんが、実際の作業でコードを最適化および改善し、実行効率を改善し、実際の値を生成するための基本的なツールとして使用します。例として、可変検索メカニズムを取ります。コードが深くネストされており、グローバル変数を参照するたびに、JSエンジンはスコープチェーン全体を探します。たとえば、スコープチェーンの下部にあるウィンドウとドキュメントオブジェクトにこの問題があります。したがって、この問題をめぐる多くのパフォーマンス最適化作業を行うことができます。もちろん、最適化には他の側面があります。ここでは詳しく説明しません。この記事は、チップオフと見なされています!
@一竞2015による
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。