繼上篇匿名函數的this指向問題後,續寫和總結JavaScript中函數的this指向問題,下文將介紹有關函數this綁定的四條規則。segmentfault
關於函數的this,經常有句話,叫作誰調用就指向誰
。簡單來講this的指向跟函數的調用位置緊密相關,要想知道函數調用時this到底引用了什麼,就應該明確函數的調用位置。通常來講須要經過函數的調用棧來判斷來分析出函數真正的調用位置,具體怎麼分析呢?除了目測代碼(就是盯着看-。-)外,還也能夠借用瀏覽器的開發者工具(debug工具),去推斷目標函數究竟是在哪裏調用的,這樣才能更準確的知曉this的指向。好比下面這段代碼:瀏覽器
function foo() { console.log('foo') } function bar() { console.log('bar') foo() } bar()
要想知道foo函數是由誰調用的,就能夠在瀏覽器中打開調試工具,在foo函數中的第一行打一個斷點,找到函數的調用棧,而後再找到棧中的第二個元素,這就是真正的調用位置。以下圖所示:
從瀏覽器的調試工具能夠找到foo函數的真正調用位置。app
默認綁定規則通常用於函數獨立調用時。如下面的代碼爲例:函數
var a = 2 function foo() { var a = 3 console.log(this.a) } foo() // 2
輸出結果爲2。由於foo函數調用時處於全局環境下(這裏是window),查看一下瀏覽器中的調用棧:工具
調用棧中只有foo函數一個元素,說明調用者就是當前的全局環境window,因此這裏的this指向的就是window,由於最外部的a一開始是最爲window.a 聲明並賦值的,因此能夠理解爲this = window; this.a = 2
。比較特殊的一點就是,若是在foo函數內部採用了嚴格模式,那麼this就會綁定到undefined:學習
var a = 2 function foo() { 'use strict' var a = 3 console.log(this.a) } foo() //`//Cannot read property 'a' of undefined`
舉以下代碼爲例:優化
var a = 2 function foo() { console.log(this.a) } var obj1 = { a:3, foo: foo } obj.foo() //3
輸出結果爲3,說明這裏的this指向的是obj1,爲何再也不是指向全局環境了呢。在這裏就要考慮到調用位置是否存在上下文對象,或者說是否被某個對象擁有或包含。在上述的代碼中,foo函數的引用被賦給了obj1的foo屬性obj1.foo = foo
, 而且在foo函數被調用時,它的前面也加上了對obj1的引用。此時,當函數引用有上下文對象時,隱式綁定規則就會將函數中的this綁定到這個上下文對象,這裏的上下文對象就是obj1。
其實在理解上下文對象時,我的以爲不用那麼抽象,它無非就是一個不肯定的代名詞,簡單來講你以爲它是什麼,那它就是什麼(-。-)。this
默認綁定和隱式綁定在我看來是js的一個內置且被動的綁定方式,就是已經這麼幫你設定好了,只要符合這兩個規則且沒有其餘規則存在那麼this的指向就按照這兩個規則來。顯然,這類被動的綁定方式並不符合實際的代碼編寫須要,好比我要指定一個函數的this,該怎麼辦呢?這時候就須要顯式綁定了。call、apply會在顯式綁定時發揮做用。參考以下代碼:編碼
function foo() { console.log(this.a) } var obj1 = { a: 2 } var a = 3 foo.call(obj1) //2
輸出結果爲2。緣由是由於call改變了foo函數運行的this指向,將本來this指向的window全局轉爲了指向obj1,因此輸出的是2,從這裏也能夠看出,顯示綁定的優先級大於默認綁定。spa
首先應該明確一點,JavaScript中的new與其餘面向類的語言不一樣,在js中new後面的只不過是一個普通的函數,僅僅是被new操做符調用了而已。使用new調用函數時,會執行以下步驟:
代碼以下所示:
function foo(a) { this.a = a } var bar = new foo(2) console.log(bar.a) //2
輸出結果爲2。
ES6中出現了一種特殊的函數:箭頭函數。以上的四種規則在箭頭函數中都不適用,箭頭函數的是根據外層函數或者全局鏈決定this的。其實這也是對以往ES6以前的較爲複雜的this綁定規則的優化和統一,在實際編碼的過程當中更容易讓人理解,固然箭頭函數也有缺點,這裏就再也不展開。
在寫這篇總結文章以前,一直對js中的this問題理解不深,翻了幾遍《你不知道的js》纔算真正有所學習和領悟。本文寫的並不具體,就this綁定時的綁定丟失問題並無展開敘述,綁定的規則優先級也沒有寫全,暫時先留個坑,等忙完這陣再來補充-。- !