`Array.prototype.forEach(callback[, thisArg])` 的 `thisArg` 行為在 ES6 標準化時引發熱議:為什麼默認 `this` 不指向當前元素?
arr.forEach(function(element, index, array) {
// this 默認指向:
// - 非嚴格模式:window (全局對象)
// - 嚴格模式:undefined
}, thisArg); // 顯式傳入則綁定 this
回調函數接收三個參數:element、index、array。當前元素已作為第一參數直接可用,無需通過 `this` 獲取。這符合「顯式優於隱式」原則。
`this` 在 JS 中代表調用上下文。`forEach` 是數組方法,其調用上下文理應是數組本身(`arr`),而非元素。若默認 `this = element`,則破壞了方法調用的語義統一性。
早期庫(Underscore, Lodash)的 `_.each(list, iteratee, [context])` 習慣將 `context` 綁定到 `iteratee` 的 `this`。ES6 標準化時選擇了與原生 `call/apply` 一致的語義,而非迎合庫的習慣。
// 現代寫法:箭頭函數無 this,直接用外層 this,或用參數
arr.forEach((element, index) => {
console.log(this.config, element); // this 詞法綁定外層
});
// 需要綁定 this 時,顯式傳入
arr.forEach(function(element) {
this.handle(element); // this = controller
}, controller);
| 特性 | forEach | for...of | map |
|---|---|---|---|
| 返回值 | undefined | undefined | 新數組 |
| 中斷遍歷 | 不可 (需 throw/every/some) | ✅ break/continue/return | 不可 |
| 異步支持 | 不支持 (需自行 Promise.all) | ✅ 配合 await | 不支持 |
| this 綁定 | 支持 thisArg | 詞法作用域 | 支持 thisArg |
ES6 規定 `forEach` 默認 `this = undefined/global` 而非 `element`,是基於參數完備性、語義一致性、語言演進連續性的理性選擇。現代開發配合箭頭函數,`this` 問題已非痛點。理解設計初衷,才能寫出符合語言哲學的代碼。