Is foreach (Array.prototype.forEach
) guaranted to loop in the same order every time over the same data set? And why?

- 3,624
- 7
- 44
- 60
-
What loop and what object? – SLaks Nov 29 '18 at 19:53
-
Because `forEach` is not asynchronous? It takes next argument only if the previous iteration has finished. And of course if you are not calling any asynchro function in that loop. – kind user Nov 29 '18 at 19:53
-
1Do you mean `Array.prototype.forEach`? And what do you mean by *"why"*? – jonrsharpe Nov 29 '18 at 19:53
-
1Sure, but if the function supplied to it does some asynchronous processing with the value, there is no guarantee that that processing happens in any particular order. `[1, 2, 3, 4, 5].forEach((n) => setTimeout(() => console.log(n), Math.random() * 1000))` – Scott Sauyet Nov 29 '18 at 19:57
-
@jonrsharpe I mean I wanted to understand what's behind the order logic in either case. – Xsmael Nov 29 '18 at 20:19
2 Answers
If the implementation is sticking to the standard then yes, forEach
processes the array in order except for sparse arrays where uninitialized values are ignored. forEach()
is described in the spec:
forEach calls callbackfn once for each element present in the array, in ascending order. callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.
It loops through the index starting with:
Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length" Let k be 0.
Repeat, while k < len
...
Increase k by 1
In javascript Arrays are objects and have a length
property and integer keys which are the indexes. The spec is saying it will start at k=0
and call the arr[k]
in increasing order for k < length
. It will call the callback for all values where arr
has a property k
An example of a sparse array where forEach
ignores elements might look like this:
let a = Array(10)
a[5] = "Five"
a[9] = "Nine"
console.log(a)
// ignores initialized values:
a.forEach((item) => console.log(item))
If you are doing asynchronous things inside the callback, it can appear that the callback is not happening in order, but it still is.
EDIT based on comment:
You can with a little hacking pass an object to forEach
that looks like an array (it has a length and integer keys). forEach
will call the items in index order, not the order they are defined on the object. For example:
// an object that has enough info
// for forEach to use
let o = {
3: "three",
2: "two",
0: "zero",
1: "one",
length: 4
}
// calls in order of indexes, not order keys were defined
Array.prototype.forEach.call( o, (i) => console.log(i))

- 90,562
- 7
- 108
- 148
-
does it really loop "in ascending order" or according to the order in wich each elements of the object has been define – Xsmael Nov 29 '18 at 20:23
-
1@Xsmael see the edit for an edge case example. `forEach` calls in ascending order of key which in the case of arrays is the index. – Mark Nov 29 '18 at 20:26
Yes, forEach will wait for the previous item to complete before processing the next one
//Sync methods;
[1,2,3].forEach(function(e){
console.log(e)
});
//Output:
//1
//2
//3
If you're using Async methods inside the loop, they will be called in order but the loop will not wait for the callback.
//Async Methods
[1,2,3].forEach(function(e){
someAsyncMethod(e, console.log);
});
//Output example:
//3
//1
//2
This answer have some methods to use async functions inside foreach.
As for why, there is an international standard called ECMAScript all JavaScript implementations should adhere to it; the behaviour of Array.prototype.forEach()
is specified in this standard.
You cand find the specification and the pseudo-code for Array.prototype.forEach()
at ECMAScript® 2018 Language Specification

- 793
- 6
- 21