iT邦幫忙

2025 iThome 鐵人賽

DAY 3
0
Modern Web

JavaScript 進階修煉與一些 React ——離開初階工程師新手村的頭30天系列 第 3

離開 JS 初階工程師新手村的 Day 03|找到真正的冒險者:this 是誰

  • 分享至 

  • xImage
  •  

this 綁定

今天我們來看 JavaScript 中的 this 綁定行為,分為兩種:一般 function 和 arrow function。不過在深入探討前,我們先從本質上來看,JS 的 this 與其他語言有什麼不同,以 C++ 為例:

指向了誰

C++ 這類的物件導向語言, this 固定指向函式被呼叫的物件實體,但 JS 的 this 指向由函式呼叫方式決定(動態決定),可以是全域物件、指定物件,甚至是 undefined(嚴格模式下)。

嚴格模式(Strict mode)是 JavaScript 在 ES5 之後新增的一種語法特性,透過它可以讓 JS 以更嚴謹的方式執行,幫助開發者避免一些常見錯誤。

如何綁定

C++ 會在編譯時,自動把 this 帶入 member function,可以很直觀的理解成上述「this 永遠指向該物件本身」的實作;JS 則是執行時,依函式呼叫方式動態綁定。🫥⋯⋯什麼,實在是太抽象的話,我們看一個例子

https://ithelp.ithome.com.tw/upload/images/20250914/20168365z7viAUMw3Z.png

person.greet() 中,對於 greet() 來說的 thisperson,因此可以正確的 console 出

Hi, I am Alice

但是,當呼叫 greetFn() 時,即便他被 assign 成 person.greet,當他被呼叫的時候,他的 this 會被動態決定,有可能是一個全域物件,因此只會得到以下的結果(因為全域物件沒有 name )

Hi, I am

所以在使用 JS 的 this 時要特別注意綁定到的對象為誰,我們可以透過最一開始提到的 arrow function 來避免 refer 到預期外的 this ,主要原因是因為箭頭函式沒有自己的 thisthis 由外層作用域決定。

丟失 this 的範例

https://ithelp.ithome.com.tw/upload/images/20250914/20168365WmInWmcNXk.png

雖然我們預期過一秒之後,obj.sayHi 會被呼叫,但這裡 setTimeout 拿到的是 obj.sayHi 的「引用」,沒有透過 obj 來呼叫,所以 this 丟了。

解法一:用箭頭函式把this包起來

setTimeout(() => obj.sayHi(), 1000); // this 保留在 obj 中,正確印出 Miya

這邊的 obj.sayHi() 還是透過 obj 呼叫的,因此 thisobj,沒問題!

另一個例子是即便我們使用 class,仍然可能會丟失 this ,同樣的可以使用 arrow function callback 來保留 class 裡的 this

https://ithelp.ithome.com.tw/upload/images/20250914/201683656H2GY8fmAD.png

解法二:用 bind 綁定 this

bind 會回傳一個新的函式,將 this 綁定到你指定的物件。這邊的例子中 sayHi 裡的 this 透過 bind 綁定到obj上,this.name 就可以正確印出 "Miya"

setTimeout(obj.sayHi.bind(obj), 1000);

接著,我們來看 React 裡頭如何使用 class fields + arrow function 解決 this 丟失問題
https://ithelp.ithome.com.tw/upload/images/20250914/20168365txEpTjPaMK.png

handleClick 是以箭頭函式定義的 class field,會自動綁定 this 到當前的 class instance。因此,handleClick 傳給 <button>onClick 時,裡面的 this 不會丟失,也不需要在 constructor 裡手動綁定。

不過現在的主流寫法(≥ React 18)已經不再寫 class component 而是 functional component,事件處理不需要手動綁定 this,只要使用箭頭函數就能用外層作用域,這個情況下根本沒有 this 的問題!

https://ithelp.ithome.com.tw/upload/images/20250914/20168365eA6s4EBkgB.png


上一篇
離開 JS 初階工程師新手村的 Day 02|閉!殺!技!:閉包 Closure
下一篇
離開 JS 初階工程師新手村的 Day 04|時間迷宮:事件循環 Event Loop
系列文
JavaScript 進階修煉與一些 React ——離開初階工程師新手村的頭30天4
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言