Skip to content

2026-06-24

/ 13 分鐘閱讀

/ Deep JavaScript Foundations v3

預設綁定:this 的第四種做法與總覽 ​

本篇延續前兩篇對 this 綁定規則的介紹。前三種規則分別是隱式綁定、明確綁定與 new 綁定。本篇說明最後一種規則:預設綁定(default binding),並整合四種規則建立完整的判斷框架。

規則四:預設綁定(Default Binding) ​

預設綁定是四種規則中的「兜底規則」:當呼叫一個函式時,若不符合前三種規則中的任何一種,就套用預設綁定。

最常見的情境是單純的函式呼叫,沒有任何物件、沒有 .call、沒有 .bind、也沒有 new:

javascript
var teacher = 'Kyle';

function ask(question) {
    console.log(this.teacher, question);
}

function askAgain(question) {
    'use strict';
    console.log(this.teacher, question);
}

ask("What's the non-strict-mode default?");
// Kyle What's the non-strict-mode default?

askAgain("What's the strict-mode default?");
// TypeError

非嚴格模式:this 退回全域物件 ​

在非嚴格模式下,若函式呼叫沒有任何綁定上下文,this 會預設指向全域物件(瀏覽器中是 window,Node.js 中是 global)。

上例的 ask 函式沒有使用嚴格模式,呼叫時也沒有任何上下文,因此 this 指向全域物件,而全域物件上恰好有 teacher = "Kyle",所以印出 Kyle。

嚴格模式:this 為 undefined,拋出 TypeError ​

在嚴格模式下,同樣的情況會讓 this 保持 undefined。嘗試存取 undefined.teacher 就會拋出 TypeError。

這個設計是刻意的。Kyle Simpson 的解釋是:

如果你定義了一個 this aware 的函式,卻在沒有任何 this 上下文的情況下呼叫它,這幾乎可以確定是個錯誤。嚴格模式讓這個錯誤立即浮現,而非悄悄地把 this 指向全域物件。

這個行為與「自動建立全域變數」是同一類問題:表面上可以運作,但幾乎從來不是你真正想要的結果。嚴格模式在兩種情況下都替開發者攔截了這類疏失。

四種做法完整整合 ​

至此,四種 this 綁定規則已全部介紹完畢:

規則觸發條件this 指向
隱式綁定obj.fn()呼叫點左側的物件
明確綁定fn.call(ctx) / fn.apply(ctx) / fn.bind(ctx)明確傳入的物件
new 綁定new fn()新建立的空物件
預設綁定fn()(無其他規則匹配)全域物件(非嚴格)或 undefined(嚴格)

四種規則的優先順序 ​

當一個呼叫點同時符合多種規則時(雖然不建議這樣寫,但語言上是合法的),JavaScript 有明確的優先順序決定哪條規則生效。

判斷 this 指向時,依序問以下四個問題,第一個符合的規則就是答案:

1. 函式是否用 new 呼叫? 是 → this 指向新建立的空物件。

2. 函式是否用 .call()、.apply() 或 .bind() 呼叫? 是 → this 指向明確傳入的上下文物件。(.bind() 底層使用 .apply(),屬於同一條規則。)

3. 函式是否透過上下文物件呼叫(如 workshop.ask(...))? 是 → this 指向該上下文物件。

4. 以上皆否? 非嚴格模式 → this 退回全域物件。嚴格模式 → this 為 undefined,拋出 TypeError。

判斷 this 的正確方式 ​

整個 this 系統的核心結論只有一句話:

判斷 this 指向什麼,唯一的方法是看呼叫點(call site),也就是函式是如何被呼叫的,而非函式是如何被定義的。

每次函式被呼叫,「呼叫的方式」就決定了 this 的綁定結果。沒有其他方法可以事先從函式定義推斷出 this 的值。

複習 ​

JavaScript 中呼叫函式並綁定 this 的四種方式是什麼? ​

  1. 預設綁定(default binding)
  2. 明確綁定(explicit binding,使用 call/apply/bind)
  3. 隱式綁定(implicit binding,透過上下文物件)
  4. 建構子綁定(constructor binding,使用 new 關鍵字)

在嚴格模式下,若呼叫一個含有 this 的函式卻沒有提供上下文,會發生什麼事? ​

this 會是 undefined,嘗試存取其屬性時會拋出 TypeError,防止意外參考全域物件。

在非嚴格模式下,若呼叫一個含有 this 的函式卻沒有提供上下文,會發生什麼事? ​

this 會退回全域物件作為預設綁定,這通常不是預期的行為。

如何判斷一個函式中 this 的值? ​

必須檢查呼叫點(call site)以及函式被呼叫的方式,而非看函式本身的定義。

嚴格模式為何在沒有提供上下文時,將 this 設為 undefined? ​

這是為了防止開發者在沒有適當上下文的情況下,不小心呼叫了一個 this aware 的函式,這種情況幾乎可以確定是一個錯誤。

小測驗 ​

在嚴格模式下,若函式在沒有任何上下文的情況下被呼叫,會發生什麼事? 因為 `this` 是 `undefined`,會拋出 TypeError
在 JavaScript 中,有幾種方式可以呼叫函式並綁定 `this`? 四種
要判斷函式中 `this` 指向什麼,應該看哪裡? 呼叫點(call site)以及函式被呼叫的方式
在非嚴格模式下,若函式在沒有上下文的情況下被呼叫,`this` 的預設行為是什麼? 退回全域物件
嚴格模式為何在沒有上下文時,讓 `this` 為 `undefined`? 用來提示在沒有上下文的情況下呼叫 `this` aware 函式,幾乎可以確定是一個錯誤

此文章是 FrontendMasters 上的 Deep JavaScript Foundations, v3 課程筆記

最後更新時間:

Buy Me A Coffee

系列章節 第 59 篇 / 共 69 篇

0 %
MIT Licensed | Copyright © 2025-present Wen-Hsiu's Blog
Photo by Federica Galli on Unsplash