先簡單說兩句
相信很多朋友在剛學習Javascript都被Javascript的this弄得很混亂,由於我一開始就是學習Java先的,很自然就Java中的this代入了Javascript中,其實這是一個重大的錯誤,有人(我)說「如果上帝用七天打造這個世界,那麼Javascript就是在最後0.01秒才匆匆設計的」,現在就讓我跟大家詳細說說Javascript的this吧!
this的意義
在Java中,this是一個引用對象,引用的就是這個對象自身,在Javascript中也會有這種場景,如以下代碼的this便指向new出來的那個對象自身
1 | export class People{ |
又或者在使用Javascript的對象時,this也是指向car對象本身,但這種情況上面跟通過new關鍵字又有一些不一樣。
1 | const car = { |
在我現在的工作中,經過需要使用到React,一般在React的constructor中需要做以下這件事,就是需要bind綁定,為甚麼需要呢,不綁定會怎樣?
1 | export class Input extends React.Component{ |
還有一種更簡單的情況,在瀏覽器打開chrome devTools,在console面版中輸入this,看看會出現甚麼東西。為甚麼會輸出window呢?

接著我跟大家解釋釋,究竟this的意義是甚麼,其實this是指運行期間的上下文,根據不同的情況有不同的綁定規則。
this的綁定規則
默認綁定
默認綁定就是最簡單的情況,在全域或者不在函數內部使this的時候,this指向的便全局變量,在瀏覽器中是window,在nodejs中便是global,默認綁定會在嚴格下失效,即嚴格模式,默認綁定的this會指向undefined。上面第四個例子便是默認綁定。
隱式綁定
當函數被調用時,若函數引用具有上下文對象,則隱式綁定會將 this 綁定到這個上下文對象。第二個例子說的就是隱式綁定,在this的綁定規則裡,最容易出錯的就是隱式綁定,來看一段代碼,最後的那兩個函數會分別返回a和surprise,這種情況叫做隱式丟失,丟失的就是this,bar是obj.foo的一個函數別名,在調用bar的時候會丟失對obj的this引用,而直接是綁定到全局的對象中。
1 | // 非嚴格模式 |
顯式綁定
顯式綁定就要為了避免隱式丟失的出現,通過apply、call和bind三個方法來顯式的綁定要調用函數內部的this,看看例子最直接,在例子就直接指定this的值,這樣可以避免出現丟失的問題,所以現在為甚麼第三個例子中React constructor需要用bind綁定一下。
1 | const obj1 = { |
new綁定
第一個例子中,我們通過一個new關鍵字「實例化」了一個對象,實際上的new過程只做了下面幾件事:
- 創建一個新的對象
- 將新的對象的
__prototype__屬性指向函數的prototype - 將函數的
this綁定向新的對象 - 調用函數
注意第三步,這裡就是實際上new綁定出現的原因,因為在new關鍵字的執行過程已經把新創建的對象綁定到函數的this裡,所以在new出來的對象裡面的this在運行時是會指向這個對象的。
優先級
依次為new綁定、顯式綁定、隱式綁定、默認綁定。
Javascript中的this機制其實還有一層,就是this在prototype原型鏈上的查找,可以理解this是一個二維平面,水平方向是綁定規則,垂直方向就是prototype原型鏈和JS的各種作用域。
下期將為大家介紹Javascript的原型鏈和作用域。
本人獻醜了,大家加油~!
