2024-11-21 情境式說明 vue 的this

2024-11-21 情境式說明 vue 的this

this 確實有點麻煩,因為它的值會根據執行時的情境(上下文)改變。讓我們用一個生活化的情境來類比說明,這樣更容易理解。


情境設定:餐廳服務員的角色變化

假設我們有一位服務員(你可以把他想像成代碼中的 this),他在不同場合有不同的「職責」(上下文),因為他身處的情境會影響他應該「服務」誰。


情境 1:在餐廳工作

1
2
3
4
5
6
7
8
const restaurant = {
name: "美味餐廳",
service: function () {
console.log(`歡迎光臨 ${this.name}`);
},
};

restaurant.service(); // 歡迎光臨 美味餐廳
  • 服務員的角色(this): 他在餐廳,當然知道服務的是餐廳的客人。
  • 結果: 他會正確地說出餐廳的名字。

類比:

在這裡,this 指向 restaurant,因為 service 方法是從 restaurant 物件內被調用的。


情境 2:被外派到婚禮現場

1
2
3
const weddingEvent = restaurant.service;

weddingEvent(); // 歡迎光臨 undefined
  • 服務員的角色(this): 被派去婚禮現場,但沒有告訴他婚禮現場的名字,他變得迷茫。
  • 結果: 他無法正確地說出「歡迎光臨」後的內容。

類比:

this 失去了原本的指向,默認指向全局(瀏覽器中是 window,Node.js 中是 global)。window.name 默認是 undefined,所以輸出結果不完整。


情境 3:在婚禮現場給他備忘錄

1
2
const weddingEvent = restaurant.service.bind({ name: "幸福婚禮會場" });
weddingEvent(); // 歡迎光臨 幸福婚禮會場
  • 服務員的角色(this): 他被給了一張備忘錄,知道現在要服務的是「幸福婚禮會場」。
  • 結果: 他可以正確地說出「歡迎光臨幸福婚禮會場」。

類比:

在這裡,我們使用了 bind 方法,手動把 this 綁定到 { name: "幸福婚禮會場" }


情境 4:服務員的記性不好,用了箭頭函式

1
2
3
4
5
6
7
8
const restaurant = {
name: "美味餐廳",
service: () => {
console.log(`歡迎光臨 ${this.name}`);
},
};

restaurant.service(); // 歡迎光臨 undefined
  • 服務員的角色(this): 他記不住自己身處的地方,只認為是「上級指派」的。
  • 結果: 他不知道當前餐廳的名字。

類比:

箭頭函式中的 this 不會指向當前物件,而是根據外層上下文來決定。這裡的外層上下文是 window,所以 this.nameundefined


情境 5:用箭頭函式保證清晰記憶

1
2
3
4
5
6
7
8
9
10
11
const restaurant = {
name: "美味餐廳",
service() {
const reminder = () => {
console.log(`歡迎光臨 ${this.name}`);
};
reminder();
},
};

restaurant.service(); // 歡迎光臨 美味餐廳
  • 服務員的角色(this): 他得到了一個隨身備忘錄(箭頭函式),隨時告訴他「你是在餐廳裡」。
  • 結果: 他正確地服務客人。

類比:

箭頭函式不會創建自己的 this,所以會自動繼承外層函式的上下文(restaurant),因此能正確使用 this.name


Vue 中的情境:碼表應用的 this 問題

讓我們用你的 Vue 碼表作例子:

問題情境:傳統函式導致 this 丟失

1
2
3
4
5
6
7
methods: {
startTimer: function () {
setInterval(function () {
console.log(this.time); // `this` 是 `window`,time 是 undefined
}, 1000);
}
}
  • 服務員的角色(this): 他去做定時器的工作,但忘了自己屬於 Vue 實例。
  • 結果: Vue 實例的 time 無法被訪問,因為 this 指向 window

解決方法:用箭頭函式

1
2
3
4
5
6
7
methods: {
startTimer: function () {
setInterval(() => {
console.log(this.time); // 正確的 `this` 指向 Vue 實例
}, 1000);
}
}
  • 服務員的角色(this): 他隨身帶著備忘錄(箭頭函式),記得自己是 Vue 實例的一部分。
  • 結果: 他能正確操作 Vue 實例的數據。

總結:情境帶出的 this 特性

  1. this 的值由執行上下文決定。

    • 普通函式this 由調用方式決定,默認指向全局物件。
    • 箭頭函式this 繼承自定義它時的外層上下文。
  2. 在 Vue 中,保持 this 指向 Vue 實例很重要。

    • 用箭頭函式可以避免上下文丟失。
    • 或者用 bindthat 保存正確的上下文。
  3. 生活化類比:

    • 「服務員在不同情境下服務不同的對象」形象地描述了 this 的上下文問題。