Javascriptはコンテキストとスコープチェーンを実行します.

6821 ワード

一、作用域Scopeと文脈Contect
    javascriptでは、スコープとコンテキストcontextは2つの異なる概念です.各関数の呼び出しは、scopeとcontextを伴っています.本質的には、scopeは関数と結合されています.contextはオブジェクトに基づいています.すなわち、scopeは、関数呼び出し時に変数アクセスを提供するために使用され、関数呼び出しごとに異なる.contextは常にキーワードthisの値であり、現在実行されているコードが属するオブジェクトを指す.scopeスコープ    前編の「javascript変数」の部分でjavascriptの役割領域を議論しました.大局と局部に分けて、javascriptの中にはブロックの役割領域がありません.
*'this'contextコンテキスト*.    contextはしばしば関数で呼び出される方式で決定される.(1)関数がオブジェクトとして呼び出された場合、thisはその関数が属するオブジェクトに設定されます.如き
var obj = {
    foo: function() {
        return this;   
    }
};
obj.foo() === obj; // true。 this  obj  
(2)newキーワードを使って新しい関数オブジェクトを作成する場合、thisの値も新規作成された関数オブジェクトに設定されます.たとえば
function foo() {
    alert(this);
}
foo() // window
new foo() // foo
(3)関数が一般的に呼び出された場合、thisはグローバルcontexまたはブラウザのwindowオブジェクトである.たとえば
function foo() {
    alert(this);
}
foo() // window
二、関数ライフサイクル
    関数のライフサイクルは、作成と実行の二つの段階に分けられます.    関数の作成段階では、JS解析エンジンが事前解析を行い、関数宣言を前倒ししながら、この関数をグローバルスコープまたは現在の関数の前段の関数のローカルスコープに配置します.    関数の実行段階では、JS解析エンジンは、現在の関数の局所変数と内部関数を事前に宣言してから、トラフィックコードを実行します.関数が終了したら、関数の実行コンテキストを解放して、関数の局所変数をログアウトします.
三、変数オブジェクト
VOとAO    VO(Varable Object)変数オブジェクトは、関数作成段階、JS解析エンジンによる事前解析時に、すべての変数と関数の声明(JSエンジンの前解析段階でVOの内容が確定されますが、この場合はほとんどの属性の値がundefinedです.)に対応します.VOは実行コンテキストに関連して、自分のデータがどこに記憶されているかを知り、どのようにアクセスするかを知る.VOは実行コンテキストに関する特殊なオブジェクトで、コンテキストで宣言された以下の内容を格納しています.(2)関数宣言(FuntionDeclaration、略語はFD)(3)関数の参照
function add(a,b){
    var sum = a + b;
    function say(){
        alert(sum);
    }
    return sum;
}
// sum,say,a,b        VO,            undefined
    AO(Activation Object)は、関数が実行を呼び出すと、関数に必要なすべての変数が含まれている実行コンテキストを作成します.この変数は、新しいオブジェクトがActivation Objectです.オブジェクトは、(1)関数のすべての局所変数(2)関数の命名パラメータ宣言(3)関数のパラメータセットを含んでいます.
function add(a,b){
    var sum = a + b;
         var x = 10;
    function say(){
        alert(sum);
    }
    return sum;
}
add(4,5);
//  AO = {
//      arguments : [4,5],
//      a : 4,
//      b : 5,
//          x: undefined
//      say : ,
//      sum : undefined
//  }
変数オブジェクトVOに関するより詳細な知識は、アクセスしてください.http://www.cnblogs.com/TomXu/archive/2012/01/16/2309728.html
四、実行コンテキスト
    実行コンテキスト(execution context)は、ECMAScript仕様でJavaScriptコードの実行を記述するための抽象概念です.すべてのJavaScriptコードは、ある実行コンテキストで実行されます.現在の実行コンテキストでは、新しい実行コンテキストに入ります.このfunctionは呼び出しが完了すると元の実行コンテキストに戻ります.Functionが起動中に異常を投げ、捕獲されなかった場合、複数の実行コンテキストから退出する可能性がある.function呼び出し中に、他のfunctionを呼び出して、新しい実行コンテキストに入ることができ、これによって実行コンテキストスタックが形成される.
    各実行コンテキストは、一つのスコープ(scope chain)に関連している.このスコープは、function実行時に識別子の値を求めるために使用される.このチェーンには複数のオブジェクトが含まれています.識別子の値を求める過程で、チェーンの最初のオブジェクトから開始され、次に、あるオブジェクトの中に識別子名と同じ属性が見つかるまで、後のオブジェクトを逐次検索します.各オブジェクトで属性検索を行う場合、そのオブジェクトのプロトタイプチェーンが使用されます.一つの実行文脈では、その関連する作用ドメインチェーンはwith文とcatch子文にのみ影響される.
コンテキストのプロパティを実行    各実行文脈には三つの重要な属性があります.変数オブジェクト、スコープとthisはもちろんいくつかの他の属性があります.[][3]
    セクションjavascriptコードが実行されると、javascript解釈器はExecution Conteextを作成して使用します.ここには2つの段階があります.フェーズ/コード実行フェーズ(a)をアクティブにして変数の値、関数の参照を設定し、コードを解釈/実行します.
段階(1)(b)でVO/AOを作成すると、解釈器は主に以下のことをした.(1)関数のパラメータに基づいてパラメータリストを作成し、初期化する(2)関数の内部コードをスキャンして、関数宣言を検索します.見つかったすべての内部関数宣言に対して、関数名と関数をVO/AOに引用して保存します.VO/AOに同名の関数がすでにある場合、上書きします.(3)関数の内部コードをスキャンして、変数宣言を検索します.見つかったすべての変数宣言に対して、VO/AOに変数名を入れて、undefinedに初期化します.変数名とすでに宣言されている形式のパラメータまたは関数が同じであれば、変数宣言はすでに存在しているこのような属性(つまり変数無効)に干渉しません.
function foo(i) {
    var a = 'hello';
    var b = function privateB() {

    };
    function c() {

    }
}
foo(22);
「作成段階」では、次のExecution Conteet objectが得られます.
fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: undefined,
        b: undefined
    },
    this: { ... }
}
「アクティブ/コード実行フェーズ」では、Execution Conteet objectが更新されます.
fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: 'hello',
        b: pointer to function privateB()
    },
    this: { ... }
}
    関数は、定義時にその作用領域と作用ドメインチェーン(静的)を決定し、呼び出し時にのみ実行コンテキストを作成します.(1)呼び出し時のイメージを含み、関数内の関数宣言と変数は、アクティブオブジェクトAOを作成します.(2)そして、AOを実行コンテキストの作用ドメインチェーンの最前端に押し込み、コンテキストを実行する作用ドメインチェーンは、それが起動している関数の[scope]属性から得られた(動的);(3)実行コンテキストオブジェクトにもthisの属性が含まれている.
五、作用ドメインチェーンscope chain
    各実行コンテキストには、自分の変数オブジェクトがあります.大域コンテキストでは、大域オブジェクト自体です.関数については、アクティブオブジェクトです.作用するフィールドチェーンは、親変数オブジェクトを含むコンテキストのすべての変数オブジェクトを実行するリストです.このチェーンは、クエリー識別子に使用されます.
var x = 10;
function foo() { 
  var y = 20; 
  function bar() {
    alert(x + y);
  } 
  return bar; 
}
foo()(); // 30
上記の例では、barコンテキストの作用ドメインチェーンは、AO(bar)->AO(>>VO(global)を含む.
ドメインチェーンはどうやって作りますか?    前述したように、スコープChainは、コンテキストExecution Conteetを実行する属性です.関数が実行されるときに実行される関数の[scope]属性によって得られます.    関数の作成時:javascriptでは、関数もオブジェクトで、関数が作成された時に書き込みます.これは関数オブジェクトのすべての親変数オブジェクトの階層チェーンです.関数というオブジェクトに存在します.    関数実行時:実行コンテキストExecution contextを作成し、実行コンテキストExecution contextを実行して、AOを関数[[scope]の一番前に置いて、実行コンテキストのScope chainとします.すなわち、Scope chain(実行コンテキストの属性、ダイナミック)=AO|VO(実行コンテキストの属性、ダイナミック)+[Scope]
一例
var x = 10; 
function foo() {
  var y = 20; 
  function bar() {
    var z = 30;
    alert(x +  y + z);
  } 
  bar();
}
foo(); // 60
グローバルコンテキストの変数オブジェクトは、
globalContext.VO === Global = {
  x: 10
  foo: 
};
「foo」作成時の「foo」の[scope]属性は以下の通りです.
foo.[[Scope]] = [
  globalContext.VO
];
「foo」がアクティブになったとき(コンテキストに入る)、「foo」のコンテキストのアクティブオブジェクトは以下の通りです.
fooContext.AO = {
  y: 20,
  bar: 
};
「foo」コンテキストのスコープは次の通りです.
fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.: 
fooContext.Scope = [
  fooContext.AO,
  globalContext.VO
];
内部関数「bar」が作成された場合、その[[scope]は以下の通りです.
bar.[[Scope]] = [
  fooContext.AO,
  globalContext.VO
];
「bar」がアクティブになった時、「bar」コンテキストのアクティブオブジェクトは以下の通りです.
barContext.AO = {
  z: 30
};
「bar」コンテキストのスコープは、
barContext.Scope = barContext.AO + bar.[[Scope]] // i.e.:
 
barContext.Scope = [
  barContext.AO,
  fooContext.AO,
  globalContext.VO
];
「x」、「y」、「z」の識別子の解析は以下の通りである.
  • 「x」--barConttext.AO/not found--fooConttext.AO/not found--global Conttext.VO/found-10
  • “y”--barConttext.AO/not found--fooConttext.AO/found-20
  • 「z」--barConttext.AO/found-30
  • スコープチェーンに基づく変数クエリ    コード実行時にある変数値にアクセスする必要がある場合、JSエンジンは、Execution contextのscope chainで最初から最後まで検索します.scope chainのある要素の中で変数が見つけられますか?見つけられません.