js thisバインディング機構の深さと詳細


本論文の例はjs thisバインディング機構を述べている。皆さんに参考にしてあげます。具体的には以下の通りです。
関数の呼び出し先
語法のスコープとは反対に、thisの指向は関数が動作するときに決定され、それは動的であり、関数の呼び出し位置によって変化する。
thisを理解するには、まず呼出位置を理解する必要があります。呼出位置とは、関数がコード内で呼び出される位置です。呼び出し位置をよく分析してこそ、この問題に答えられます。このthisは一体何を引用していますか?

function baz() {
//       :baz
//   ,            
console.log( "baz" );
bar(); // <-- bar     
}
function bar() {
//       baz -> bar
//   ,       baz 
console.log( "bar" );
foo(); // <-- foo     
}
function foo() {
//       baz -> bar -> foo
//   ,       bar 
console.log( "foo" );
}
baz(); // <-- baz     

多くの近代的なデスクトップブラウザは開発者ツールを内蔵しています。ツールで関数の最初の行のコードにブレークポイントを設定したり、最初の行のコードの前にdebuggerを挿入したりできます。語句コードを実行すると、その位置でデバッタが一時停止し、現在位置の関数呼び出しリストを表示します。これがあなたの呼び出しスタックです。したがって、thisの結合を分析したいなら、開発者ツールを使って、スタックを呼び出して、スタックの中の第二の要素を見つけてください。これが呼び出された位置です。
thisバインディング規則
関数の呼び出し位置は、呼び出し位置を見つけたら、次の4つのルールのどれを適用するべきかを判断します。
独立関数呼び出し
独立関数呼び出しは、環境オブジェクトを含む関数呼び出しの位置を指します。

function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 2

オブジェクトとしてのメソッド呼び出し
関数があるオブジェクトの方法として呼び出されると、thisはこのオブジェクトを指します。

function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2

特に、関数fooはobjオブジェクトではないが、呼び出し位置は、Objのコンテキストを使用して関数を呼び出す。私はいつも呼び出し位置の重要性を強調しています。うっかりしたら無視するかもしれません。下の列を見てください。

function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; //     !   1
var a = "oops, global"; // a        
bar(); // "oops, global"   2

ステップ1では、変数barは、実際に関数fooを指すobj.fooの参照である。だからbarを使うのはfooを直接使うのと同じです。
使用.call/.appyバインディング
関数を作成するたびに、この関数は2つの継承方法があります。
これらの最初のパラメータはオブジェクトで、オブジェクトはthisに結合されます。次に関数を呼び出すときにこのthisを指定します。直接にthisのバインディングオブジェクトを指定することができますので、明示的バインディングと呼びます。

function foo() {
console.log( this.a );
}
var obj = {
a:2
};
foo.call( obj ); // 2
newバインディング
newを使って関数を呼び出すか、またはコンストラクターの呼び出しが発生した場合、自動的に次の操作が実行されます。
  • 新しいオブジェクトを作成します。
  • この新しいオブジェクトは、構造関数のプロトタイプFoo.prototypeを指して[プロトタイプ]接続されます。
  • この新しいオブジェクトは、関数で呼び出されたthisに結合されます。
  • 関数が他のオブジェクトに戻っていない場合、new式の関数呼び出しは自動的にこの新しいオブジェクトに戻ります。
  • 
    function foo(a) {
    this.a = a;
    }
    var bar = new foo(2);
    console.log( bar.a ); // 2
    
    
    newを使ってfoo(.)を呼び出すと、新しいオブジェクトを作成してfoo(.)呼び出し中のthisに結合します。
    優先度
    実行中の関数のthisバインディングを判断するには、この関数の直接呼び出し位置を見つける必要があります。見つかったら、次の4つの規則を順次適用して、thisのバインディングオブジェクトを判断します。
  • はnewで呼び出されますか?新規作成したオブジェクトに結合します。
  • はcallまたはappy(またはbind)によって呼び出されますか?指定されたオブジェクトにバインドされます。
  • はコンテキストオブジェクトによって呼び出されますか?そのコンテキストオブジェクトに結合します。
  • デフォルト:厳密なモードでundefinedにバインドされ、そうでないとグローバルオブジェクトにバインドされます。
  • 注意してください。いくつかの呼び出しは、デフォルトのバインディングルールを不用意に使うかもしれません。もし「より安全」にthisバインディングを無視したいならば、全体のオブジェクトを保護するために、DMZオブジェクトを使用することができます。
    興味のある友達はオンラインHTML/CSS/JavaScriptコードを使ってツールを実行できます。http://tools.jb51.net/code/HtmlJsRun上記コードの運行効果をテストします。
    もっと多くのJavaScriptに関する内容は当駅のテーマを調べられます。「JavaScript常用関数技術のまとめ」、「javascript対象向け入門教程」、「JavaScriptエラーとデバッグテクニックのまとめ」、「JavaScriptデータ構造とアルゴリズム技術のまとめ」及び「JavaScript数学演算の使い方のまとめ
    本論文で述べたように、JavaScriptプログラムの設計に役に立ちます。