這個 this 到底是什麼?
這個(this)到底是哪個?
基本上這個(this)脫離物件呼叫,就沒有太大的意義。
在 JavaScript 中,this 是一個經常讓人困惑的關鍵字,因為它的值在不同的情況下會有所變化。this 的值取決於函數的呼叫方式,而不是函數定義的地方。本文將介紹 this 在不同情況下的指向,並討論 call、apply、bind 這三種方法,以及如何解決 this 綁定的問題。
函數呼叫方式
在講解this前,我們要先知道 function 在呼叫時,有幾種方法
- 作為函數去呼叫
- 作為方法去呼叫
- 作為建構式用
new的方式呼叫 - 透過
apply、call的方式呼叫
1 | function sayByeBye(name) { |
一般情況下的 this
全域環境下的 this
在全域範圍中(非嚴格模式),this 指向全域物件(在瀏覽器中是 window)。
例如:
1 | console.log(this); // 在瀏覽器中,輸出 window |
物件方法中的 this
當函數作為物件的方法呼叫時,this 指向該物件。例如:
1 | const obj = { |
在這裡,this指向obj,因此this.name取到的是obj.name。
獨立函數中的 this
當函數在全域範圍中獨立呼叫時,this在非嚴格模式下會指向全域物件(瀏覽器中的window)。在嚴格模式下,this則會是undefined。
1 | function showThis() { |
嚴格模式中的 this
在嚴格模式下,this不再自動指向全域物件,如果函數獨立呼叫,this會是undefined。
1 | ; |
new 建構函數使用 this
當使用new關鍵字來呼叫並建構函數時,this的指向會有所不同。
new會建立一個新的實體物件,並且this會指向新創建的物件,而不是全域物件或其他任何物件。
1 | function Person(name) { |
使用箭頭函數的正確綁定在
introduceArrow方法中,我們使用了箭頭函數。箭頭函數不會自己創建this,而是從其外部環境繼承this。在這裡,外部環境是Person的實例,因此this仍然指向Person實例,能夠正確地存取 name 屬性。使用普通函數的錯誤綁定在
introduceRegular方法中,我們使用了普通函數。這樣做會導致setTimeout中的回調函數創建自己的this,並且這個this指向全域物件(在瀏覽器中為window)或undefined(在嚴格模式下)。
因此,當回調函數執行時,this.name無法正確取得name屬性,結果是undefined。
修正錯誤綁定的方法
如果我們希望修正普通函數中的this綁定,可以使用bind方法或將回調函數改為箭頭函數。
使用bind方法
1 | function Person(name) { |
使用箭頭函數
1 | function Person(name) { |
在以上修正方法中,bind方法可以將this繫結到指定的物件,而箭頭函數可以自動繼承外部環境中的this。這樣可以確保在回調函數中,this可以正確地指向實例對象。
call、apply 與 bind 解決 this 綁定
當我們希望手動指定this的值時,可以使用call、apply或bind。
每個 function 都會自帶這些方法可以呼叫直接呼叫使用。
call
call方法允許我們明確地設定this的值並立即執行該函數。它的語法是:
1 | function.call(thisArg, arg1, arg2, ...)。 |
第一個參數,就是我們要指定的this
1 | function introduce(greeting) { |
apply
apply與call類似,不同的是,apply接受的是一個參數陣列而不是單獨的參數。
1 | function introduce(greeting) { |
apply對於參數的傳遞方式更加靈活,尤其在參數數量不確定時。
bind與call和apply不同的是,bind並不會立即執行函數,它會返回一個新的函數,並將this永遠綁定到指定的物件。
1 | function introduce(greeting) { |
常見問題與解決方法
問題:回調函數中的 this 不正確
在回調函數(例如事件處理器、setTimeout)中,this的值通常會出現問題,因為它可能會指向全域物件或undefined。解決這個問題的方法包括使用bind或箭頭函數。
使用bind
1 | const button = document.getElementById('myButton'); |
使用箭頭函數
箭頭函數不會自己綁定this,而是繼承外部環境中的this。
1 | const obj = { |
範例
1 | const obj = { |