剛入門javascript,關於this的學習,花了本身挺多的時間,作了比較多的功課,看了一篇又一篇的文章,也看了一些書籍,今天就結合看的那些東西總結下本身所學到的東西,方便留着之後回看,進一步的學習,這篇文章會不斷的更新,不斷的更新本身的想法,如今仍是一個入門不久的小白,如有錯誤,懇請指出!javascript
this這個關鍵字在整個javascript中用處挺普遍的,例如,在閉包,對象等中都會用到,掌握好this我的認爲是學好javascript的關鍵之一了,固然其中還有:閉包、原型、原型鏈、對象等理論基礎也是幾個關鍵點,都得用心的學習。java
函數中的調用數組
javascript函數中this的指向不是在函數定義的時候肯定的,而是在函數調用時肯定的,用我本身的話來講:就是看這個函數是在什麼環境下被調用的,若是在全局環境下調用這個函數,那麼這個函數中的this就指向了window,看下面的這個例子:閉包
var a = 2; function foo() { console.log(this.a);//2 } foo();
函數foo()的調用是在全局環境下調用的,即這個函數中的this指向的就是window(其實這也能夠叫函數的默認綁定,在後面我會介紹),函數控制檯輸出的就是window.a,函數內部即便沒有定義變量,一樣也是能夠輸出a的值,這其中也涉及到了做用域鏈的相關知識點,由內向外搜索,這裏就不解釋了,這個能夠本身去了解。
加大一點難度,看看這個例子,可能會讓你開始有點迷惑,我本身在不是很理解this在函數中的調用,是很迷惑的,不懂,相關知識點一遍一遍的反覆的看,你們來看看,是上面的例子的改版:app
var a = 2; function foo() { var a = 3; console.log(this.a);//2 } foo();
這個函數foo()的輸出值,你們應該會感到很意外,我去,a怎麼會輸出的是2,不該該是3的嗎,是否是有問題啊,哈哈哈哈哈,起初我是以爲是有問題的,函數中明明也聲明瞭一個變量a,輸出的值確定是3啊,想了一些時間沒有想明白。回過頭來看看this是怎麼說的,就清楚了爲何a輸出的值依舊是2了:javascript函數中this的指向不是在函數定義的時候肯定的,而是在函數調用時肯定的。認真的解讀下這句話就很清楚的知道變量a輸出的值確定就是2了,this的指向只與普通函數的調用有關,箭頭函數另外再說,這個foo()函數的調用時在全局環境,所以this是指向全局對象,即window,因此輸出a的值依舊仍是2了,而不是想固然的認爲是3了,這下應該比較清楚了吧。你們再看下下面的這個例子:函數
var a = 2; function foo() { a = 3; console.log(this.a); } foo();
這個foo()函數輸出的又是什麼值呢,這個就是你們認爲的3了,這就不解釋了,看了上面的應該就比較清楚了。學習
綁定規則this
默認綁定code
函數獨立調用,直接使用不帶任何修飾的函數引用進行調用,其this默認指向window對象,第一部分的第一個例子就是默認綁定,這就不在記述。對象
隱式綁定
函數調用時擁有一個上下文對象,就好像這個函數是屬於這個對象的同樣。例如:
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; obj.foo();//2
當函數foo()被調用時,其引用有obj這個對象,即函數調用中的this綁定到了這個對象,this.a就至關於obj.a,輸出的值就爲2。
隱式綁定丟失
被隱式綁定的函數丟失綁定對象,其會應用默認綁定,這也是this應用中容易出錯的地方,關鍵仍是對this調用位置沒有理解清楚。例如:
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo }; var bar = obj.foo; var a = '全局'; bar();// '全局'
其實很好理解爲何this指向的全局對象window,關鍵仍是看函數的調用位置,雖然函數foo()被看成引用添加到obj對象中,它也僅僅是一個引用,變量bar也就是obj.foo的一個引用的傳遞,然而bar()是獨立調用的,不帶任何修飾的函數調用,因此函數調用中的this是綁定到了全局對象,即this.a是window.a,輸出的值爲'全局'。
顯式綁定
顯式綁定多數是用call()、apply()函數,他們的第一個參數是一個對象,是給this準備的,函數調用時將其綁定到this,也就是直接指定this的綁定對象。例如:
function foo(){ console.log(this.a); } var obj = { a:2 }; foo.call(obj);//2
經過call(),調用foo時強制把它的this綁定到obj上。
apply()的使用和call()同樣,它們不一樣的在於傳參的方式不同,call()接受的是若干個參數的列表,apply()接受的是一個包含多個參數的數組,具體做用能夠本身去了解。
new綁定
若是是一個構造函數,用new來調用,那麼綁定的將是新建立的對象。例如:
function foo(a){ this.a = a; } var bar = new foo(2); console.log(bar.a);//2
使用new來調用foo()時,構造一個新的對象並把它綁定到函數調用中的this上面,即this.a就是bar.a,輸出的值爲2。
箭頭函數this問題
箭頭函數體內的this對象就是定義時所在的對象,而不是使用時所在的對象,固定不變。例如:
function foo(){ setTimeout(()=>{ console.log(this.a); },100); } var obj = { a:2 } foo.call(obj);//2 function foo(){ setTimeout(function(){ console.log(this.a); },100); } var obj = { a:2 } foo.call(obj);//undefined
看上面的兩個例子,第一個使用的是箭頭函數,第二個使用的是普通函數,最後的結果不同的,輸出一個是2,一個是undefined。緣由很簡單,箭頭函數中this對象是在定義所在的的對象,普通函數中的this對象的指向是可變的。
本例第一個用例中箭頭函數中的this老是指向函數定義生效時所在的對象,即爲obj,因此箭頭函數的this.a就是obj.a,輸出的值就爲2。第二個用例中,根據調用的位置,普通函數this的指向是可變的,這個用例中this的最終指向的是全局對象window,即this.a就是window.a,全局環境中沒有定義變量啊,因此輸出的值爲undefined。爲何第二個用例的this指向的是全局對象,有一種解釋是:對象中的方法的函數被看成函數模式所觸發,因此它的this是指向window的,這也是this應用容易出錯的一個地方。若是也想讓它的this指向定義時綁定的對象,作以下改變就好了:
function foo(){ var that = this; setTimeout(function(){ console.log(that.a); },100); } var obj = { a:2 } foo.call(obj);//2
將this臨時傳遞給一個變量that,經過that使用,這樣輸出的值就爲2了。
結束
1.this的掌握的關鍵在於它的調用位置,這個理解清楚了就不太容易出錯。2.要區分好普通函數和箭頭函數中this的使用,不要搞混淆了。3.學好這些理論基礎是學好javascript的基石,對之後理解和寫javascript的邏輯提供很好的幫助