実例解析javascriptの中のthis

2910 ワード

thisキーワードはJavascriptの中で最も複雑なメカニズムの一つです.thisの主な理解は、thisでのバインディングオブジェクトを知ることである.面接においても、プロジェクト開発においても、thisの習得は不可欠です.話は多くないです.まず例を見てみます.
//"use strict";         
var name = "global name";
var obj = {
  name:"obj name",
  getName: function(){
    console.log(this.name);  //(1)
    return function(){
      console.log(this.name);  //(2)
    }
  }
}
//    
obj.getName()();   //  "obj name"  "global name"
var getName2 = obj.getName;
getName();   //  "global name"   "global name"
注:標準モードでは上の出力ですが、厳格モードでは(2)TypeError:Canot read property'name'of undefinedをエラーします.この例には主に二つのthisのポイントがあります.
  • デフォルトのバインディングと暗黙のバインディング.デフォルトのバインディングはグローバル変数にthisを結びつけるものですが、厳密なモードは例外的で、thisはundefinedにバインドされます.デフォルトのバインディングの場合:独立関数呼び出し、匿名関数.
  • 暗黙的なバインディングの場合、関数呼び出し中のthisは、「抱擁」または「包含」という関数のオブジェクトコンテキストに結びつけられます.暗黙的に失われた場合、thisはまたデフォルトのバインディングを適用します.したがって、上記の例では、オブジェクトobjに関数getName()を宣言した.Obj.get Name()を呼び出した時、この時はObjオブジェクトがそれを持っていますので、そのthisはObjに結び付けられました.つまり、この時(1)のthis.name=obj.nameです.そして、呼び出された後に匿名関数が返されます.だからobj.get Name();匿名関数を実行させ、このとき(2)のthisをwindowに結びつけると、「global name」が出力されます.
  • 私たちが再び一つのgetName 2を定義すると、それは実際にはObj.getNameの参照であり、実際にはそれはgetName関数だけを参照しています.この時のgetName 2は、実際には修飾されていない関数として呼び出されています.したがって、デフォルトのバインディング、すなわち暗黙的な損失を適用しました.上の例に続いて、もう2つの関数を実行します.
    getName2().call(obj);    //"global name"  "obj name"
    (getName2.call(obj))();   //"obj name"  "global name"
    
    コールの使い方に詳しい人なら、正しい答えが出せるはずです.これがthisの第三のポイントです.顕式結合です.すなわち関数は、call(...)とappy(...)の方法を使用して、thisのバインディングオブジェクトを指定することができます.get Name 2().call(obj)すなわち、コールバック関数のthis表示をobjに結びつけることに相当するので、第二の出力はobj.nameとなる.get Name 2.cal(obj)get Name 2のthisをobjに結びつけることに相当するので、(get Name 2.cal(obj)();とobj.get Name();等価です
    OKです.じゃ続けます.
    var a;
    function foo(a){
      this.a = a;
    }
    foo(1);
    var bar = new foo(2);
    console.log(a);    //1
    console.log(bar.a);    //2
    
    emmは上のような結果がよく分かります.しかし、これはthisバインディングの第4のルールです.newバインディングです.ついでに、newを使って関数を呼び出したり、コンストラクターの呼び出しがあった場合、自動的に実行されます.1)全く新しいオブジェクトを作成(構築)する.2)この新しいオブジェクトは[prototype]接続されます.3)この新しいオブジェクトは、関数で呼び出されたthisに結合されます.4)関数が他のオブジェクトに戻っていない場合、new式の関数呼び出しは自動的にこの新しいオブジェクトに戻ります.最後に4つのバインディングの優先度:newバインディング>明示的>暗黙的>デフォルト
    随堂テストです
    // 1
    function foo(){
      console.log(this.a);
    }
    var obj2 = {
      a:1,
      foo:foo
    };
    var obj1 = {
      a:2,
      obj2:obj2
    };
    
    obj1.obj2.foo();   //1
    
    // 2
    function foo(){
      console.log(this.a);
    }
    function doFoo(fn){
      fn();
    }
    var obj = {
      a:2,
      foo:foo
    };
    var a = "global";
    doFoo(obj.foo);   //  "global"
    //              ,   var fn = obj.foo;  fn();
    
    // 3
    function foo(){
      console.log(this.a);
    }
    var obj1 = {
      a:1,
      foo:foo
    };
    var obj2 = {
      a:2,
      foo:foo
    };
    obj1.foo();  //1
    obj2.foo();  //2
    
    obj1.foo.call(obj2);  //2
    obj2.foo.call(obj1);   //1