Array.prototype.forEach()

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

forEach() 方法的 Array 例項為陣列中的每個元素執行一個提供的函式。

試一試

const array = ["a", "b", "c"];

array.forEach((element) => console.log(element));

// Expected output: "a"
// Expected output: "b"
// Expected output: "c"

語法

js
forEach(callbackFn)
forEach(callbackFn, thisArg)

引數

callbackFn

為陣列中的每個元素執行一個函式。該函式的返回值將被忽略。該函式將使用以下引數進行呼叫:

element

陣列中正在處理的當前元素。

index

陣列中正在處理的當前元素的索引。

array

呼叫 forEach() 的陣列。

thisArg 可選

在執行 callbackFn 時用作 this 的值。請參閱 迭代方法

返回值

無(undefined)。

描述

forEach() 方法是一個迭代方法。它會按升序索引順序為陣列中的每個元素呼叫一次提供的 callbackFn 函式。與 map() 不同,forEach() 始終返回 undefined 並且不可鏈式呼叫。典型的用例是在鏈式呼叫的末尾執行副作用。有關這些方法的一般工作原理,請閱讀迭代方法部分。

callbackFn 僅對具有已賦值的陣列索引呼叫。對於稀疏陣列中的空槽,它不會被呼叫。

forEach() 方法是通用的。它只期望 this 值具有 length 屬性和整數鍵屬性。

除了丟擲異常外,沒有辦法停止或中斷 forEach() 迴圈。如果你需要這種行為,forEach() 方法就不是正確的工具。

可以使用諸如 forfor...offor...in 之類的迴圈語句來實現提前終止。像 every()some()find()findIndex() 這樣的陣列方法在不再需要進一步迭代時也會立即停止迭代。

forEach() 期望一個同步函式 — 它不會等待 Promise。在使用 Promise(或 async 函式)作為 forEach 回撥時,請務必瞭解其含義。

js
const ratings = [5, 4, 5];
let sum = 0;

const sumFunction = async (a, b) => a + b;

ratings.forEach(async (rating) => {
  sum = await sumFunction(sum, rating);
});

console.log(sum);
// Naively expected output: 14
// Actual output: 0

要順序或併發地執行一系列非同步操作,請參閱Promise 組合

示例

將 for 迴圈轉換為 forEach

js
const items = ["item1", "item2", "item3"];
const copyItems = [];

// before
for (let i = 0; i < items.length; i++) {
  copyItems.push(items[i]);
}

// after
items.forEach((item) => {
  copyItems.push(item);
});

列印陣列內容

注意:為了在控制檯中顯示陣列的內容,你可以使用 console.table(),它會列印陣列的格式化版本。

以下示例說明了一種使用 forEach() 的替代方法。

以下程式碼會為陣列中的每個元素列印一行

js
const logArrayElements = (element, index /*, array */) => {
  console.log(`a[${index}] = ${element}`);
};

// Notice that index 2 is skipped, since there is no item at
// that position in the array.
[2, 5, , 9].forEach(logArrayElements);
// Logs:
// a[0] = 2
// a[1] = 5
// a[3] = 9

使用 thisArg

以下(人為的)示例會從陣列中的每個條目更新物件屬性

js
class Counter {
  constructor() {
    this.sum = 0;
    this.count = 0;
  }
  add(array) {
    // Only function expressions have their own this bindings.
    array.forEach(function countEntry(entry) {
      this.sum += entry;
      ++this.count;
    }, this);
  }
}

const obj = new Counter();
obj.add([2, 5, 9]);
console.log(obj.count); // 3
console.log(obj.sum); // 16

由於 forEach() 提供了 thisArg 引數(this),因此它在每次呼叫 callback 時都會被傳遞給它。回撥函式將其用作其 this 值。

注意:如果傳遞的回撥函式使用了箭頭函式表示式,則可以省略 thisArg 引數,因為所有箭頭函式都具有詞法繫結的 this 值。

物件複製函式

以下程式碼會建立給定物件的副本。

建立物件副本的方法有多種。以下僅為一種方法,旨在解釋 Array.prototype.forEach() 如何使用 Object.* 工具函式。

js
const copy = (obj) => {
  const copy = Object.create(Object.getPrototypeOf(obj));
  const propNames = Object.getOwnPropertyNames(obj);
  propNames.forEach((name) => {
    const desc = Object.getOwnPropertyDescriptor(obj, name);
    Object.defineProperty(copy, name, desc);
  });
  return copy;
};

const obj1 = { a: 1, b: 2 };
const obj2 = copy(obj1); // obj2 looks like obj1 now

展平陣列

以下示例僅用於學習目的。如果你想使用內建方法來展平陣列,可以使用 Array.prototype.flat()

js
const flatten = (arr) => {
  const result = [];
  arr.forEach((item) => {
    if (Array.isArray(item)) {
      result.push(...flatten(item));
    } else {
      result.push(item);
    }
  });
  return result;
};

// Usage
const nested = [1, 2, 3, [4, 5, [6, 7], 8, 9]];
console.log(flatten(nested)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

使用 callbackFn 的第三個引數

如果你想訪問陣列中的另一個元素,array 引數就很有用,尤其是在你沒有引用陣列的現有變數時。以下示例首先使用 filter() 提取正數,然後使用 forEach() 列印其鄰居。

js
const numbers = [3, -1, 1, 4, 1, 5];
numbers
  .filter((num) => num > 0)
  .forEach((num, idx, arr) => {
    // Without the arr argument, there's no way to easily access the
    // intermediate array without saving it to a variable.
    console.log(arr[idx - 1], num, arr[idx + 1]);
  });
// undefined 3 1
// 3 1 4
// 1 4 1
// 4 1 5
// 1 5 undefined

在稀疏陣列上使用 forEach()

js
const arraySparse = [1, 3, /* empty */, 7];
let numCallbackRuns = 0;

arraySparse.forEach((element) => {
  console.log({ element });
  numCallbackRuns++;
});

console.log({ numCallbackRuns });

// { element: 1 }
// { element: 3 }
// { element: 7 }
// { numCallbackRuns: 3 }

對於索引為 2 的缺失值,回撥函式不會被呼叫。

在非陣列物件上呼叫 forEach()

forEach() 方法讀取 thislength 屬性,然後訪問鍵為小於 length 的非負整數的每個屬性。

js
const arrayLike = {
  length: 3,
  0: 2,
  1: 3,
  2: 4,
  3: 5, // ignored by forEach() since length is 3
};
Array.prototype.forEach.call(arrayLike, (x) => console.log(x));
// 2
// 3
// 4

規範

規範
ECMAScript® 2026 語言規範
# sec-array.prototype.foreach

瀏覽器相容性

另見