年明けから仕事への熱意があまり高くない今日この頃です。朝起きたくない、起きても仕事に行きたくない。当然、休暇前も私の仕事への熱意は非常に高く、小さなプログラムプロジェクトを立ち上げることを考えていましたが、休暇から戻った後の私の仕事のスタイルはまったく異なりました。重度のホリデー後症候群にかかっているような気がします。幸いなことに、今週は完全に無駄ではなかったことを示すためにいくつかの記事を書きました。この記事では、変数オブジェクトについて紹介します。
JavaScriptでは、必然的に変数と関数を宣言する必要がありますが、JSパーサーはどのようにしてこれらの変数を見つけるのでしょうか?また、実行コンテキストについてさらに理解する必要があります。
前の記事では、関数が呼び出される (アクティブ化される) と、新しい実行コンテキストが作成されることをすでに知っていました。実行コンテキストのライフサイクルは、2 つの段階に分けることができます。
作成フェーズ
このフェーズでは、実行コンテキストは変数オブジェクトを作成し、スコープチェーンを確立し、このポイントを決定します
コード実行フェーズ
作成が完了すると、実行が開始されますこの時点で、コードは変数の割り当て、関数 reference を完了し、他のコードを実行します。
ここから、実行コンテキストには変数オブジェクト、スコープチェーン、thisなどが含まれるため、実行コンテキストを詳細に理解することが非常に重要であることがわかります。多くの人は理解していませんこれは非常に重要な概念なので、JavaScript を本当に理解できるかどうかに関係します。以下の記事で 1 つずつ詳しくまとめます。ここでは、まず変数オブジェクトを理解することに焦点を当てます。
変数オブジェクトの作成は、以下のような処理を順に経ていきます。
引数オブジェクトを作成します。現在のコンテキストのパラメータを確認し、オブジェクトの下に属性と属性値を確立します。
現在のコンテキストの関数宣言、つまり function キーワードを使用して宣言された関数を確認します。変数オブジェクトに関数名を含む属性を作成します。属性値は、関数が配置されているメモリ アドレスへの参照です。関数名属性がすでに存在する場合、その属性は新しい参照によって上書きされます。
現在のコンテキストで変数宣言を確認し、変数宣言が見つかった場合は、変数オブジェクトに 変数名 の属性を作成します。属性値は未定義です。変数名の属性が既に存在する場合、同名の関数が未定義に変更されるのを防ぐため、そのままスキップされ、元の属性値は変更されません。
このルールによれば、変数のプロモーションを理解するのは非常に簡単になります。変数プロモーションについては多くの記事で言及されていますが、変数オブジェクトの作成プロセスを使用して、面接中に変数プロモーションを面接官に説明し、すぐに改善できるようにすることができます。
上記のルールでは、関数宣言が var 宣言よりも高い優先順位 を持つことがわかります。誰もが変数オブジェクトをよりよく理解できるように、いくつかの簡単な例を使用して変数オブジェクトについて説明します。
// demo01 function test() { console.log(a); console.log(foo()); var a = 1; function foo() { return 2; } } test();
をグローバル スコープで実行すると、test() の実行コンテキストが作成され始めます。理解を容易にするために、次の形式を使用して表現します test()
创建过程 testEC = { // 变量对象 VO: {}, scopeChain: {}, this: {} } // 因为本文暂时不详细解释作用域链和this,所以把变量对象专门提出来说明 // VO 为 Variable Object的缩写,即变量对象 VO = { arguments: {...}, //注:在浏览器的展示中,函数的参数可能并不是放在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声明的变量当遇到同名的属性时,会跳过而不会覆盖
// 执行阶段 VO -> AO VO = { arguments: {...}, foo: 'Hello', bar: <bar reference> }
需要结合上面的知识,仔细对比这个例子中变量对象从创建阶段到执行阶段的变化,如果你已经理解了,说明变量对象相关的东西都已经难不倒你了。
以浏览器中为例,全局对象为window。
全局上下文有一个特殊的地方,它的变量对象,就是window对象。而这个特殊,在this指向上也同样适用,this也是指向window。
// 以浏览器中为例,全局对象为window // 全局上下文 windowEC = { VO: window, scopeChain: {}, this: window }
除此之外,全局上下文的生命周期,与程序的生命周期一致,只要程序运行不结束,比如关掉浏览器窗口,全局上下文就会一直存在。其他所有的上下文环境,都能直接访问全局上下文的属性。
以上がフロントエンド応用編(3):変数オブジェクトの詳細解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。