平常用this很多,對this的理解就是this是對應執行環境,然而很多時候效果並不是想要的,最近看了一些談到this的筆記和書籍,總結下。
對this的誤解:
this是指向函數本身
先上個demo吧
1 var a =0; 2 demo.a=2; 3 function demo(){ 4 console.log('ok'); 5 this.a++ 6 } 7 demo();//ok 8 console.log(demo.a);//2 9 console.log(a); //1
上面的demo已經得知,如果this是指向函數本身,那么demo.a的值應該為3,但還是2說明調用的不是demo函數。
window對象的a卻增加了,說明demo函數中的this是指向window(等會說為什么)
this是在調用時被綁定的,取決於函數的調用位置(也就是調用方法):
1.默認綁定:
最常用也是函數調用類型,當只有一個獨立函數時,this指向的是window對象(解釋上面例子為什么console.log(a)會是1)。
注意:當使用嚴格模式,this會綁定到undefined
2.隱式綁定
函數調用的位置有上下文環境(我理解為對象調用模式,函數是一個對象的方法)
var obj1={
a:2,
demo:demo
};
var obj={
a:1,
obj1:obj1
};
function demo(){
console.log(this.a)
}
obj.obj1.demo()//2
當函數的執行環境是在obj對象,this指向的就是obj。如果被包裹了幾層對象,this只會綁定最后一層對象(上面demo中this最后綁定到obj1上)
注意:1.有時我們不會寫這么長一串obj.obj1.demo,而是賦給一個變量,還能達到我們想要的效果嗎?
1 var a =0 2 var obj1={ 3 a:2, 4 demo:demo 5 }; 6 var obj={ 7 a:1, 8 obj1:obj1 9 }; 10 function demo(){ 11 console.log(this.a) 12 } 13 obj.obj1.demo(); //2 14 var fn= obj.obj1.demo; 15 fn(); //0 16 obj.dd = obj.obj1.demo; 17 obj.dd() //1
當我把obj.obj1.demo賦給fn時,再執行fn(),結果卻是0.why? 按照我們上面說的,fn()可以理解為一個獨立函數(沒有任何修飾符),其中的this就是指向window,即a=0。
我覺得還能這么理解,函數中this,取決於調用函數上一級(也就是上面說的最后一級)的對象。
如上:obj.dd = obj.obj1.demo,然后執行obj.dd(),結果是1,也就是說現在函數中你的this綁定的是obj對象。同理也可以解釋fn()其實就是window.fn(),綁定的是window對象
3.顯示綁定
顯示綁定就是通過apply,call,bind,直接將函數中的this綁定到想要的對象上
還是先看demo吧
1 var obj1={ 2 a:2, 3 demo:demo 4 }; 5 var obj={ 6 a:1, 7 obj1:obj1 8 }; 9 function demo(){ 10 console.log(this.a) 11 } 12 obj.obj1.demo(); //2 13 obj.obj1.demo.call(obj); //1 14 var fn= obj.obj1.demo.bind(obj); 15 fn() //1
簡單介紹下apply call bind。apply和call是函數內置的方法,第一個參數是指定函數執行環境,第二個參數是傳給函數的參數,call是將參數依次傳給函數,apply則是將參數組合在一個數組中,將數組傳給函數,
bind也是綁定指定執行環境,但是不會執行(使用call和apply的時,函數就執行了)
根據上面說的,正常obj.obj1.demo()得到的結果是2,但是使用call后this綁定的obj上,所以a的值為1.后面使用bind同理(只是函數沒有執行,需要執行一次)
4.構造函數模式
創建一個構造函數的實例,構造函數中的this會綁定到這個實例對象上
1 function Per(){ 2 this.a=1 3 } 4 var dd = new Per(); 5 alert(dd.a) //1
dd是Per的一個實例,this綁定在dd上,創建了dd的一個屬性a,且值為1
本文總結來源於《你不知道的JavaScript》
第一次寫博客,排版有點亂,都是一些個人理解,有問題歡迎拍磚。
補充:setTimeout中如果使用this會直接指向window對象,使用閉包調用函數中有this,也是指向window(不確定,寫的幾個demo顯示是如此)