年明けから仕事に対する熱意があまり高くなく、最近は無気力な状態が続いております。朝起きたくない、起きても仕事に行きたくない。当然、休暇前も私の仕事への熱意は非常に高く、小さなプログラムプロジェクトを立ち上げることを考えていましたが、休暇から戻った後の私の仕事のスタイルはまったく異なりました。重度のホリデー後症候群にかかっているような気がします。幸いなことに、今週は完全に無駄ではなかったことを示すためにいくつかの記事を書きました。この記事では、変数オブジェクトについて紹介します。
JavaScriptでは必然的に変数や関数を宣言する必要がありますが、JSパーサーはどのようにしてこれらの変数を見つけるのでしょうか?また、実行コンテキストについてさらに理解する必要があります。
前の記事では、関数が呼び出される (アクティブ化される) と、新しい実行コンテキストが作成されることをすでに知っていました。実行コンテキストのライフサイクルは 2 つの段階に分けることができます。
1. 作成フェーズ
このフェーズでは、実行コンテキストは変数オブジェクトを作成し、スコープチェーンを確立し、このポイントを決定します
2. コード実行フェーズ
作成が完了すると、実行が開始されます。この時点で、コードは変数の割り当て、関数の参照を完了し、他のコードを実行します。
ここから、実行コンテキストを詳細に理解することが非常に重要であることがわかります。実行コンテキストには、変数オブジェクト、スコープ チェーン、この概念や、多くの人が理解していないものの非常に重要なその他の概念が含まれるためです。は、JavaScript を本当に理解できるかに関連しています。以下の記事で 1 つずつ詳しくまとめます。ここでは、まず変数オブジェクトを理解することに焦点を当てます。
変数オブジェクト
変数オブジェクトの作成は以下のプロセスを順に経ていきます。
1.引数オブジェクトを作成します。現在のコンテキストのパラメータを確認し、オブジェクトのプロパティとプロパティ値を確立します。
2. 現在のコンテキストの関数宣言、つまり function キーワードを使用して宣言された関数を確認します。変数オブジェクトに関数名を含む属性を作成します。属性値は、関数が配置されているメモリ アドレスへの参照です。関数名属性がすでに存在する場合、その属性は新しい参照によって上書きされます。
3. 現在のコンテキストで変数宣言を確認し、変数宣言が見つかった場合は、その変数名を使用して属性値を変数オブジェクトに作成します。変数名の属性が既に存在する場合、同名の関数が未定義に変更されるのを防ぐため、そのままスキップされ、元の属性値は変更されません。
このルールによれば、変数の昇格を理解するのが非常に簡単になります。変数プロモーションについては多くの記事で言及されていますが、変数オブジェクトの作成プロセスを使用して、面接中に変数プロモーションを面接官に説明し、すぐに改善できるようにすることができます。
上記のルールでは、関数宣言が var 宣言よりも高い優先順位を持っていることがわかります。誰もが変数オブジェクトをよりよく理解できるように、いくつかの簡単な例を使用して変数オブジェクトについて説明します。
// demo01 function test() { console.log(a); console.log(foo()); var a = 1; function foo() { return 2; } } test();
上記の例では、test() の実行コンテキストから直接理解し始めます。 test() がグローバル スコープで実行されると、test() の実行コンテキストの作成が開始されます。理解を容易にするために、次の形式を使用して表現します
创建过程 testEC = { // 变量对象 VO: {}, scopeChain: {}, this: {} } // 因为本文暂时不详细解释作用域链和this,所以把变量对象专门提出来说明 // VO 为 Variable Object的缩写,即变量对象 VO = { arguments: {...}, foo: <foo reference> // 表示foo的地址引用 a: undefined }
実行フェーズに入る前は、変数オブジェクト内の属性にアクセスできません。ただし、実行フェーズに入ると、変数オブジェクトはアクティブ オブジェクトに変換され、内部のプロパティにアクセスできるようになり、実行フェーズの操作が開始されます。
このように、インタビュー中に変数オブジェクトとアクティブオブジェクトの違いについて質問された場合、実際には同じオブジェクトですが、実行コンテキストのライフサイクルが異なりますので、自由に答えることができます。
// 执行阶段 VO -> AO // Active Object AO = { arguments: {...}, foo: <foo reference>, a: 1 }
したがって、上記の例demo1では、実行シーケンスは次のようになります
function test() { function foo() { return 2; } var a; console.log(a); console.log(foo()); a = 1; } test();
理解を確実にするために、別の例を見てみましょう。
// demo2 function test() { console.log(foo); console.log(bar); var foo = 'Hello'; console.log(foo); var bar = function () { return 'world'; } function foo() { return 'hello'; } } test();
上記の知識を組み合わせて、この例の作成段階から実行段階までの変数オブジェクトの変更を注意深く比較する必要があります。すでに理解している場合は、変数オブジェクトに関連するすべてのことはもう難しくないことを意味します。あなたのために。
グローバルコンテキストの変数オブジェクト
ブラウザを例にとると、グローバルオブジェクトはウィンドウです。
グローバル コンテキストには特別な場所があり、その変数オブジェクトはウィンドウ オブジェクトです。この特集は窓にも当てはまります。
// 创建阶段 VO = { arguments: {...}, foo: <foo reference>, bar: undefined } // 这里有一个需要注意的地方,因为var声明的变量当遇到同名的属性时,会跳过而不会覆盖
さらに、グローバル コンテキストのライフ サイクルは、プログラムのライフ サイクルと一致します。ブラウザ ウィンドウを閉じるなど、プログラムが終了しない限り、グローバル コンテキストは常に存在します。他のすべてのコンテキストは、グローバル コンテキストのプロパティに直接アクセスできます。