JavaScriptコアの実行コンテキスト、作用ドメインチェーン、クローズド
6222 ワード
実行コンテキストEC(Execution Contect)実行コンテキストは、1つの関数またはグローバルコードが実行される場合の環境であり、実行時に必要とされるデータを含み、オブジェクトとして理解できる. 関数は、実行毎に新しい実行コンテキストを作成します. 関数は、実行が終わるたびに、この実行コンテキストを破棄します. 実行スタックCS(call stack)関数が実行されるたびに、実行コンテキストが新たに生成され、管理実行コンテキストのスタックが実行スタックである. は、関数が実行されると、実行前に実行コンテキストを生成してスタックに組み込み、関数の実行が終了するとスタックが出てきます. は、各実行中の関数がスタックトップのコンテキストで使用される. スタックの底は常にグローバルコンテキストである. 例を挙げますは、グローバルコンテキスト
実行スタック:
G_EC
は、foo関数を実行し、
実行スタック:
foo_EC
G_EC
は
実行スタック:
グラムEC
foo_EC
G_EC
実行スタック:
foo_EC
G_EC
は
実行スタック:
bar_EC
foo_EC
G_EC
は
実行スタック:
グラムEC
bar_EC
foo_EC
G_EC
ここの です.
実行スタック:
bar_EC
foo_EC
G_EC
実行スタック:
foo_EC
G_EC
実行スタック:
G_EC
すべてのコードが実行され、
実行スタック:
空
コンテキストの内容を実行は、関数が実行される前の瞬間に生産される. はスタック上部のVOを実行し、実行対象AOとも呼ばれる. は、スタックの底のVOを実行し、グローバルオブジェクトGO(Global Object)とも呼ばれる. 2.作用ドメインチェーンSC(Scope Chin)スコープチェーンは、コンテキストを実行するセットであり、各関数には「scope」属性があり、配列を指し、配列には自分の実行コンテキスト以外の実行コンテキストが保存されています. 作用分域チェーンは、関数定義時に生成される. 関数が変数を使用するときは、まず自分の実行文脈から検索します.見つけられない場合は、スコープに沿って上に探します. 3.this
コンテキストとしての実行の理解に影響しないでスキップします.グローバル環境において、 を指す.関数の を指す.は を指す.は、オブジェクト内の関数を呼び出し、 を指す.
VOの作成過程
一つの関数のVOを作成する時、jsエンジンがすること.は、モダリティの値 を決定する.変数の宣言は を上げます.は、実参加の値を形参 に割り当てる.関数ステートメント全体のアップグレード 同名の属性があると上書きされます.
例を挙げます
SCの内容
SC=前の階層でコンテキストスタックを実行するAO+上の階層でコンテキストスタックのSCを実行します.
例を挙げます
関数内のサブ関数が保存されると、その関数の外部には閉じられたパケットが形成されます.
しかし、は、公有変数を実現する. はキャッシュしてもいいです. は、属性の私有化を実現する. モジュール化し、グローバル変数の汚染を防止する.
function foo() {
console.log('foo ');
function bar() {
console.log('bar ');
}
bar();
}
foo();
コード実行時、実行スタックはどのように変化しますか?G_EC
を作成し、スタックに組み込む.実行スタック:
G_EC
foo
の実行コンテキストfoo_EC
を作成し、スタックに組み込む.実行スタック:
foo_EC
G_EC
console.log
関数を実行し、console.log
関数の実行コンテキストclg_EC
を作成し、スタックに組み込む.実行スタック:
グラムEC
foo_EC
G_EC
console.log
の実行が完了し、「foo関数が実行されました」とプリントアウトし、clg_EC
を廃棄し、スタックを出ます.実行スタック:
foo_EC
G_EC
bar
関数を実行し、bar
の実行コンテキストbar_EC
を作成し、スタックに組み込む.実行スタック:
bar_EC
foo_EC
G_EC
console.log
関数を実行し、console.log
関数の実行コンテキストclg_EC
を作成し、スタックに組み込む.実行スタック:
グラムEC
bar_EC
foo_EC
G_EC
ここの
clg_EC
は全く新しい文脈で、前とは違ってconsole.log
の実行が完了し、「bar関数が実行されました」とプリントアウトし、clg_EC
を廃棄し、スタックを出ます.実行スタック:
bar_EC
foo_EC
G_EC
bar
関数の実装が完了し、bar_EC
を廃棄し、スタックを取り出す.実行スタック:
foo_EC
G_EC
foo
関数の実装が完了し、foo_EC
を廃棄し、スタックを取り出す.実行スタック:
G_EC
G_EC
が破棄され、スタックが出ます.実行スタック:
空
//
EC = {
VO = {...},
SC = [...],
this = [...]
}
1.変数対象VO(Varebale Object)コンテキストとしての実行の理解に影響しないでスキップします.
this
の指向問題:this
はwindow
オブジェクトconsole.log(this); //window
this
は、window
(厳格なモードでundefined
を指す)function foo(){
console.log(this); //window
}
foo();
call
、apply
を使用して呼び出され、this
はcall
/apply
の第1のパラメータvar obj = {a: 1};
function foo(){
console.log(this); //obj
}
foo.call(obj);
foo.apply(obj);
obj.fun
を用いて呼び出し、this
はobj
var obj = {
a: 1,
foo: function(){
//obj.foo():this obj,
//bar(): ,this window
console.log(this);
}
};
obj.foo();
var bar = obj.foo;
bar();
VOの作成過程
一つの関数のVOを作成する時、jsエンジンがすること.
例を挙げます
function foo(a, b){
console.log(bar); //ƒ bar(){}
console.log(a); //2
function bar(){}
var a = 1;
}
foo(2, 3);
作成手順に従ってfoo関数のVO——foo_を生成します.VO//1. ,
foo_VO = {
arguments: {...}, //arguments
a: undefined,
b: undefined,
}
//2. , a, VO a ,
foo_VO = {
arguments: {...},
a: undefined,
b: undefined,
}
//3. , foo(2, 3) 2, 3, a, b
foo_VO = {
arguments: {...},
a: 2,
b: 3,
}
//4. , foo, foo VO
foo_VO = {
arguments: {...},
a: 2,
b: 3,
foo: function(){}
}
最後のfoo関数で発生したVOオブジェクトはfoo_VO = {
arguments: {...},
a: 2,
b: 3,
foo: function(){}
}
VOの作成は関数実行前のものですので、関数は現在のVOで変数を検索できます.console.log
は関数の一番前に置いても印刷できます.a
とfoo
の値SCの内容
SC=前の階層でコンテキストスタックを実行するAO+上の階層でコンテキストスタックのSCを実行します.
例を挙げます
function foo() {
function bar() {
function baz(){
}
}
}
グローバル実行コンテキストは、最初のSCが空です.g_EC = {
SC: [],
AO: {...},
this: {...},
}
foo関数はコンテキストを実行します.ここで、SC=グローバルコンテキストのAO+グローバルコンテキストのSCです.foo_EC = {
SC: [g_EC.AO], //[g_EC.AO, ...g_EC.SC]
AO: {...},
this: {...},
}
bar関数はコンテキストを実行し、SC=foo関数はコンテキストのAO+foo関数はコンテキストのSCを実行する.bar_EC = {
SC: [foo_SC.AO, g_EC.AO], //[foo_SC.AO, ...foo_SC.SC],
AO: {...},
this: {...},
}
baz関数はコンテキストを実行し、SC=bar関数はコンテキストのAO+bar関数はコンテキストのSCを実行します.baz_EC = {
SC: [bar_SC.AO, foo_SC.AO, g_EC.AO], //[bar_SC.AO, ...bar_SC.SC],
AO: {...},
this: {...},
}
関数を実行すると、変数を検索して、先に自分のAOを検索します.もしなかったら、SCの第0項、第1項に沿って順番に探してください.SCの最後の項目が見つからないとエラーが発生します.Uncaught ReferenceError: xxx is not defined
包みを閉じる関数内のサブ関数が保存されると、その関数の外部には閉じられたパケットが形成されます.
function foo(){
var a = 1;
return function bar(){
return a;
}
}
var baz = foo();
var qux = baz();
console.log(qux); //1
foo
は運転中です.foo_EC = {
SC: [GO],
AO: {
a: 1,
...
},
this: {...},
}
foo
が実行されたら、自分の実行文脈を破壊します.その中のAOも破壊されます.しかし、
bar
は外部、つまりbaz
に保存されており、bar
の作用域SCにはfoo
のAOがあるので、これはなぜクローズドが形成されたのかを説明する.外部の関数は関数内部の変数を使用することができる.baz_EC = {
SC: [foo_EC.AO, GO],
AO: {...},
this: {...},
}
何故ならbar
関数は、グローバルスコープに保存されています.foo
のAOはずっと存在していて、破壊されないので、メモリが漏れてしまいます.使用後は元のクローズドを外すべきです.baz = null
閉塞の役割: