淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
從綁定角度來看:
- 預設綁定(Default Binding):
宣告在 Global Scope 的變數,就是全域物件(window 或 global)的屬性,所以當 function 被直接呼叫,或是用func.call(null)
,func.apply(undefine)
,此時的this
會自動指向到全域物件。在use strict
,指向到全物物件的this
則會是undefine
- 隱含式綁定(Implicit Binding):
呼叫 function 的時機點 - 顯式綁定(Explicit Binding):
用call()
,apply()
,bind()
來直接指定this
new
關鍵字綁定:
當用 new 來建立一個先的物件,這個新的物件會被設為this
綁定的目標
顯示綁定優於隱含式綁定
從規範角度來看:
太難了,看文章:JavaScript深入之从ECMAScript规范解读this
想成用 call()
來呼叫 function:
淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
呼叫 function 的方法改成用 call()
的形式來看,可以解決九成的 this
問題
例如:obj.hello()
就看成 obj.hello.call(obj)
,這時 this
就是 obj
,如果是 hello()
,因為前面沒有東西,就看成 hello.call()
,也就是 window.hello.call(window)
,window
是全域物件,在 node.js 則是 global
技術總結
- 物件導向下的
this
就是 instance 本身 - JavaScript 的
this
難懂的原因在於,JavaScript 在任何地方都可以存取到this
- 脫離了物件,
this
的值就沒有什麼意義 - 沒意義的情況下,
this
的預設綁定:- 嚴格模式下是
undefined
- 非嚴格模式下,在瀏覽器是
window
- 非嚴格模式下,在node.js 是
global
- 嚴格模式下是
- 可以用
call()
或apply()
來規定this
的值 - 也可以用
bind()
來綁定this
的值,一旦綁定了就不會再改變了 call()
,apply()
,bind()
在非嚴格模式下,傳進去的值如果是 primitive type,會強制轉換成 objectthis
的值跟作用域或程式碼的位置都無關,只跟「如何呼叫」有關- 小撇步:把 function call 轉成用
call()
,例如
const obj = {
num: 1,
log: function() {
console.log(this.num)
}
}
obj.log() // 1
obj.log.call(obj) // 轉成 call 來看,就很簡單
- 箭頭函式的
this
,就是「宣告這個箭頭函式的地方的this
是什麼」 - 箭頭函式沒有自己的
this
,所以用call()
或apply()
只能傳參數,thisArg
會被忽略 - 優先順序:new 綁定 > 顯示綁定 > 隱含式綁定 > 預設綁定
參考資料
淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
What’s THIS in JavaScript ?
鐵人賽:箭頭函式 (Arrow functions)
JavaScript深入之从ECMAScript规范解读this
箭頭函式
this 的值到底是什么?一次说清楚
JS this