JavaScript - this ?
在 JavaScript 中,this 指的是對目前執行環境的 ThisBinding。而在多數情況下,this 會因為函式的呼叫方式而有所不同。
關於 this
- 呼叫函式即生成
this,指向當前函式執行環境。 this非靜態值,影響它的因素為函式的呼叫方法。- 多數情況下,
this代表呼叫函式的物件。
| 呼叫方法 | this |
|---|---|
| Method | 呼叫函式的物件 |
| Simple function call | undefined(嚴格模式) / window(瀏覽器) / global(Node.js) |
| Arrow function | 父級函式的 this (lexical this) |
| Event listener | 添加事件的 DOM 元素 |
call、apply、bind |
指定綁定的物件 |
以方法形式(Method)呼叫函式
1 | const aben = { |
上面以 aben 物件呼叫 calcAge 方法,this 即指向 aben 物件,所以 this.year 就等於 2021。
直接呼叫函式(Simple function call)
在嚴格模式下, this 為 undefined。在非嚴格模式,瀏覽器中 this 為 window,Node.js 中 this 為 global。
1 | const obj = { |
上面程式中雖然 boo 函式是在 obj 物件的 foo 方法中被呼叫,但因為 boo 函式中沒有特別指明 this,所以預設綁定為 window。
所以 this 代表的是呼叫函式的物件,而非函式本身。
而為了使 boo 函式的 this 綁定為 obj 物件,在較舊的程式碼中通常會宣告 self 變數儲存 foo 函式的 this :
1 | const obj = { |
而在 ES6 之後的方法為使用箭頭函式 :
1 | const obj = { |
箭頭函式(Arrow function)
箭頭函式本身沒有 this,它的 this 必須從父級函式或父級作用域取得。
1 | const obj = { |
上面程式碼中因為 boo 函式為箭頭函式,所以 this 為從父級函式 foo 中所取得,指向 obj 物件。
陷阱範例 :
1 | const obj = { |
雖然上面程式中以 obj 呼叫 foo 函式,但因為 foo 函式為箭頭函式,所以從父級作用域取得的 this 為 window。
特別注意,建立物件使用的 {} 不具有區塊作用域 ! 所以 foo 函式的父級作用域為全域作用域。
因此永遠不要使用箭頭函式作為物件的方法。
事件監聽(Event listener)
事件監聽中的 this 為綁定事件的 DOM 元素。
1 | <button id="btn">點我</button> |
1 | const btnEl = document.querySelector("#btn") |
特別注意,若回調函式為箭頭函式,則 this 為從父級作用域也就是全域作用域取得之 window。
bind 與 call / apply
使用 bind、call、apply 來強制綁定 this。
bind
借用已建立的函式來創建新的函式,並將指定的物件綁訂為新函式的 this :
1 | const aben = { |
也可以在創建新函式的同時預先傳入參數 :
1 | const sum = (a, b) => { |
call / apply
使用給定的物件呼叫函式,並將 this 綁定為該物件。
使用 call :
1 | const aben = { |
使用 apply :
1 | const aben = { |
兩者差別在於傳遞參數的類型,call 為一般參數形式傳遞,apply 則是陣列形式傳遞。