[JS]大風呂敷のthis針

6243 ワード

5分間のクイックマスター版
JavaScriptを勉強し始めたばかりの頃は、よくjsの中のthisとその関連方法に惑わされました.実は私達はthisの指針を含む方法の用途によって区別すれば、thisの指針が指す対象を知ることができます.
1、直接関数呼び出し、thisポインタはグローバル環境、すなわちWindowオブジェクト、例えば
2、オブジェクト関数呼び出し、thisポインタは呼び出し関数のオブジェクト自体を指します.例えば、
var object={
    'name':"vicky",
    'sayName':function(){ console.log(this.name)}
};
object.sayName();   //this    object  ,    vicky
3、コンストラクタ呼び出し、thisポインタは新しく作成したオブジェクトを指します.例えば、
function object(name){
    this.name=name;
    console.log(this);      //  this          ,  :Object { name: "vikcy" }
    console.log(this.name);  //  :"vicky"
}
var myObject=new Object('vicky');  //  this          
4、間接関数呼び出し、例えばcall、apply方法、また特殊なbind方法があります.
詳細な分析
1、直接関数呼び出し
thisポインタはグローバル環境、すなわちWindowオブジェクトを指します.
グローバル環境で直接関数を呼び出すと、thisオブジェクトはWindowオブジェクトを指します.例えば、
var name='vicky'
function sayName(name){
    console.log(this.name);
}
sayName();   //this  window  ,            var name='vicky';  this.name  :vicky
window.sayName();  //sayName()     window.sayName()
2、オブジェクト関数呼び出し
thisポインタは、関数を呼び出すオブジェクト自体を指します.
var name='Bob';
function sayName(){
    console.log(this.name);
}
var object={'name':'vicky'};
object.sayName=sayName;          //sayName    sayName(),        ,   sayName      object.sayName
object.sayName();               //          ,this      ,    :'vicky'
sayName();                     //        sayName()   window.sayName();  :'Bob'
上記の例では、グローバル環境における直接調整関数呼び出しとオブジェクト関数呼び出し時のthisポインタの違いを説明しました.
3、コンストラクタの呼び出し
thisポインタは、新しく作成したオブジェクトを指します.
function object(name){
    this.name=name;
    console.log(this);      //  this          ,  :Object { name: "vikcy" }
    console.log(this.name);  //  :"vicky"
}
var myObject=new Object('vicky');  //  this          
冒頭の例では、構造関数が呼び出されたときに、新たに作成されたオブジェクト自体を指すことがよく説明されています.
newキーワードの開拓(スキップ可能)
しかし、ここで知識を広げたいです.なぜコンストラクションが呼び出されたのかについて話をしたいです.
実はnewのキーワードを通じて構造関数を呼び出してオブジェクトを作成する時、次のような過程があります.
1、新しいオブジェクトを作成し、構造関数のプロトタイプを継承します.
2、コール()方法を呼び出して、パラメータを受け入れて、thisの指向を修正して、この新しいオブジェクトを指します.
3、コンストラクタを実行します.コンストラクタがオブジェクトに戻ると、このオブジェクトはステップ1で作成した新しいオブジェクトに取って代わります.コンストラクタが戻り値がない場合は、ステップ1で作成したオブジェクトに戻ります.
コードでこのプロセスをシミュレートすれば、大体参考できます.
var newObject=function(func){
    var o={};  //       
    o.__proto__=func.prototype;  //      prototype
    var k=func.call(o);         //  call  ,  this  ,          
    if(typeof k=== 'object'){
        //           ,     1     ,            
        return k;
    }else{
        //            ,       1     
        return o;
    }
}
このシミュレーションのコードにはちょっと欠陥があります.欠陥はコール方法の時にパラメーターを受け入れるステップを模擬していませんが、newキーワードの理解には影響がありません.
今私達は実例を通して、上のnewキーワードの運営を理解します.
function Dog(name){
    this.name=name;
    console.log(this.name);    //  '  '
    console.log(this);        //  :Object { name: "  " }
}
Dog.prototype.sayName=function sayName(){
console.log("my name is "+this.name);
}
var animal=new Dog("  ");
animal.sayName();       //  :'my name is   '
上記のコードは、以下の点を確認することができます.
1、コンストラクタthisポインタは新しく作成したオブジェクトを指します.
2、新しいオブジェクトを作成し、構造関数のプロトタイプを継承する
3、コール()方法を呼び出し、パラメータを受け取り、thisの指向を修正し、この新しいオブジェクトを指します.
に対する
コンストラクタを実行します.コンストラクタがオブジェクトに戻ると、このオブジェクトはステップ1で作成した新しいオブジェクトに代わります.コンストラクタが値を返さない場合、ステップ1で作成したオブジェクトに戻ります.
この点については、次の例を見ています.
function Cat(){
    console.log(this);   //  :Object {  }
    console.log("cat"); 
}
function Dog(name){
    this.name=name;
    console.log(this.name);
    console.log(this);    //  :Object { name: "  " }
    return new Cat();    //    ,            
}
var animal=new Dog("  ");   //  :Object {  }
このコードは確認できます.
コンストラクタを実行します.コンストラクタがオブジェクトに戻ると、このオブジェクトはステップ1で作成した新しいオブジェクトに代わります.コンストラクタが値を返さない場合、ステップ1で作成したオブジェクトに戻ります.
この点、Docgの構造関数では最後にCatのオブジェクトを返します.したがって、animalポインタは構造関数で返したnew Cat()のオブジェクトの例を指します.
4、間接関数呼び出し、例えばcall、apply方法、また特殊なbind方法があります.
call(thisポインタが指すオブジェクト、パラメータ1、パラメータ2、...)
call方法は、関数内のthis指向を動的に設定することができ、例えば、
function Cat(age,name){
    this.name='cat';
    console.log(this);
    console.log('cat: age:'+age+",name:"+name);
}
var cat=new Cat(4,'Bob');    //  :Cat {name: "cat"} cat: age:4,name:Bob
Cat.call(this,3,'Tom');     //     call  ,  :this   Window cat: age:3,name:Tom
まず、var cat=new Cat(4,'Bob');のこの行のコードを見てください.ここのthisは新しいCatオブジェクトを指しています.出力の「cat:age:4,name:Bob」も対象の初期化時に入ってきました.Cat.call(this,3,'Tom');この行のコードは、ここでのthisはWindowオブジェクトを指しています.私たちはグローバル環境でCat.call(this,3,'Tom');方法を呼び出しました.ここでcall関数の最初のパラメータ(thisポインタが指す対象)はthisに入ってきました.グローバル環境でのthisはwindowオブジェクトを指しています.第三と第四のパラメータは、それぞれage=>3を定義しました.name=>Tom'
apply(thisポインタが指すオブジェクト、パラメータ配列またはargmentsオブジェクト)
apply方法はcall方法と同じ役割をしていますが、唯一の違いはcall方法はパラメータをいちいち入力することです.argmentsオブジェクトには関数のすべてのパラメータが含まれています.
例:
function Cat(age,name){
    this.name='cat';
    console.log(this);
    console.log('cat: age:'+age+",name:"+name);
}
var cat=new Cat(4,'Bob');    //  :Cat {name: "cat"} cat: age:4,name:Bob
Cat.apply(this,[3,'Tom']);     //     apply  ,  :this   Window cat: age:3,name:Tom
function getCat(age,name){
    Cat.apply(this, arguments);    //arguments        
}
getCat(5,"kitty");           //     apply  ,  :this   Window cat: age:5,name:kitty
ビッド(thisポインタが指す対象)
bindこの方法は、bind()関数に渡す値に結合される関数の一例を作成します.
window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
    console.log(this.color); 

} 
var objectSayColor = sayColor.bind(o); 
objectSayColor(); //      sayColor.bind(o),bind           this     o    ,
                                 objectSayColor,    :"blue"
window.objectSayColor();   //  :"blue"
最後の複数:
だから、thisの方向を知るには、まず関数の呼び方をはっきりさせて、最後に自分のこのthisの指す対象はどこから来たのかを聞くべきです.
麦です.私の文章が好きなら、いいです.