Phương thức forEach()
sẽ thực thi một hàm khi duyệt qua từng phần tử của mảng.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
Cú pháp
arr.forEach(function callback(currentValue[, index[, array]]) { //your iterator }[, thisArg]);
Parameters
callback
- Hàm sẽ thực thi lên từng phần tử của mảng được gọi, hàm này nhận 3 tham số:
currentValue
Optional- Giá trị của phần tử đang được duyệt.
index
Optional- Chỉ mục của phần tử đang được duyệt.
array
Optional- Mảng mà hàm
forEach()
đang duyệt.
thisArg
Optional-
Giá trị được gán cho từ khóa
this
bên trong hàmcallback
khi được thực thi.
Giá trị trả về
Mô tả chi tiết
forEach()
thực thi hàm callback
trong lúc duyệt tới từng phần tử của mảng theo thứ tự tăng dần. Nó sẽ không được gọi cho vị trí index đã bị xóa hoặc không được khởi tạo (đối với mảng thưa - sparse arrays).
callback
được gọi với 3 tham số:
- giá trị của phần tử
- index của phần tử
- mảng đang được duyệt
Nếu tham số thisArg
được truyền vào cho forEach()
, nó sẽ được dùng cho từ khóa this
trong hàm callback. Nếu không, giá trị undefined
sẽ được dùng cho từ khóa this
. Tóm lại, giá trị của từ khóa this
trong hàm callback
được xác định tuân theo các quy tắc thông thường để xác định this
trong một hàm.
Khoảng các phần tử được xử lý bởi forEach()
được thiết lập trước lần gọi đầu tiên của callback
. Phần tử được thêm vào mảng sau khi gọi forEach()
sẽ không được callback
bắt gặp. Nếu giá trị của các phần tử sẵn có trong mảng thay đổi, thì giá trị truyền vào callback
sẽ là giá trị lúc forEach()
gặp chúng; phần tử bị xoá trước khi bắt gặp sẽ không tính. Nếu phần tử đã gặp rồi bị loại đi (ví dụ dùng shift()
) trong quá trình lặp, các phần tử sau sẽ bị bỏ qua - xem ví dụ phía dưới.
forEach()
executes the callback
function once for each array element; unlike map()
or reduce()
it always returns the value undefined
and is not chainable. The typical use case is to execute side effects at the end of a chain.
forEach()
does not mutate the array on which it is called (although callback
, if invoked, may do so).
Khác với cú pháp lặp truyền thống, không có cách nào để ngừng vòng lặp forEach ngoài việc ném ra một ngoại lệ. Nếu vì một mục đích nào đó mà bạn cần ngừng vòng lặp thì nên dùng cách khác thay vì dùng forEach
Một số cách có thể dùng trong trường hợp đó:
- Vòng lặp for đơn giản
- Vòng lặp for...of
Array.prototype.every()
Array.prototype.some()
Array.prototype.find()
Array.prototype.findIndex()
Một số hàm khác trên kiểu mảng: every()
, some()
, find()
, and findIndex()
test the array elements with a predicate returning a truthy value to determine if further iteration is required.
Ví dụ
Converting a for loop to forEach
before
const items = ['item1', 'item2', 'item3'];
const copy = [];
for (let i=0; i<items.length; i++) {
copy.push(items[i])
}
after
const items = ['item1', 'item2', 'item3'];
const copy = [];
items.forEach(function(item){
copy.push(item)
});
Printing the contents of an array
The following code logs a line for each element in an array:
function 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
Using thisArg
The following (contrived) example updates an object's properties from each entry in the array:
function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(function(entry) {
this.sum += entry;
++this.count;
}, this);
// ^---- Note
};
const obj = new Counter();
obj.add([2, 5, 9]);
obj.count;
// 3
obj.sum;
// 16
Since the thisArg
parameter (this
) is provided to forEach()
, it is passed to callback
each time it's invoked, for use as its this
value.
If passing the function argument using an arrow function expression the thisArg
parameter can be omitted as arrow functions lexically bind the this
value.
An object copy function
The following code creates a copy of a given object. There are different ways to create a copy of an object; the following is just one way and is presented to explain how Array.prototype.forEach()
works by using ECMAScript 5 Object.*
meta property functions.
function copy(obj) {
const copy = Object.create(Object.getPrototypeOf(obj));
const propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function(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
If the array is modified during iteration, other elements might be skipped.
The following example logs "one", "two", "four". When the entry containing the value "two" is reached, the first entry of the whole array is shifted off, which results in all remaining entries moving up one position. Because element "four" is now at an earlier position in the array, "three" will be skipped. forEach()
does not make a copy of the array before iterating.
var words = ['one', 'two', 'three', 'four'];
words.forEach(function(word) {
console.log(word);
if (word === 'two') {
words.shift();
}
});
// one
// two
// four
Polyfill
forEach()
was added to the ECMA-262 standard in the 5th edition; as such it may not be present in other implementations of the standard. You can work around this by inserting the following code at the beginning of your scripts, allowing use of forEach()
in implementations that don't natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming Object
and TypeError
have their original values and that callback.call()
evaluates to the original value of Function.prototype.call()
.
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback/*, thisArg*/) {
var T, k;
if (this == null) {
throw new TypeError('this is null or not defined');
}
// 1. Let O be the result of calling toObject() passing the
// |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get() internal
// method of O with the argument "length".
// 3. Let len be toUint32(lenValue).
var len = O.length >>> 0;
// 4. If isCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
// 5. If thisArg was supplied, let T be thisArg; else let
// T be undefined.
if (arguments.length > 1) {
T = arguments[1];
}
// 6. Let k be 0.
k = 0;
// 7. Repeat while k < len.
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator.
// b. Let kPresent be the result of calling the HasProperty
// internal method of O with argument Pk.
// This step can be combined with c.
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal
// method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as
// the this value and argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined.
};
}
Đặc tả
Specification | Status | Comment |
---|---|---|
ECMAScript 5.1 (ECMA-262) The definition of 'Array.prototype.forEach' in that specification. |
Standard | Initial definition. Implemented in JavaScript 1.6. |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Array.prototype.forEach' in that specification. |
Standard | |
ECMAScript (ECMA-262) The definition of 'Array.prototype.forEach' in that specification. |
Living Standard |
Trình duyệt tương thích
BCD tables only load in the browser