# Array forEach - doesn't iterate through all elements of mutating array

**URL:** <https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176>\
**Category:** I have questions\
**Created:** [January 24, 2022, 6:58pm UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176 "2022-01-24T18:58:13Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![amkmishra](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@amkmishra](https://es.discourse.group/u/amkmishra)\
**Post date:** [January 24, 2022, 6:58pm UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/1 "2022-01-24T18:58:13Z")

</div>

Let arr=[1,2,3,4,5,6,7,8,9,10];  
let array=[];  
arr forEach(function(a,b,c){array.push(arr.pop())},this);  
console.log(array);

this should copy all the array items, but it doesn't and array only contains [10,9,8,7,6]

It seems it has been changed in last few versions, cause it worked fine earlier. It must iterate through all items.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [January 24, 2022, 7:41pm UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/2 "2022-01-24T19:41:04Z")

</div>

Versions of what?

While mutating an array while you're iterating on it has never been a good idea, the spec's semantics around that have always been somewhat deterministic.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [January 24, 2022, 8:50pm UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/3 "2022-01-24T20:50:31Z")

</div>

> [@amkmishra](#):
>
> cause it worked fine earlier.

I doubt this, as I can't see how logically this would do what you want it to do. Let's work with a smaller array, and follow it step-by-step:

```javascript
let arr=[1,2,3,4];
let array=[];
arr.forEach(function(){array.push(arr.pop())});

// We start with this:
arr=[1,2,3,4]
array=[]

// One the first iteration, we pass in the first item, `1`, into the callback
// then pop one item from array and put it onto array.
// so now we have this.
arr=[1,2,3]
array=[4]

// On the next iteratio, we pass the second item, `2`, into the callback.
// then pop one item from array and put it onto array.
// so now we have this.
arr=[1,2]
array=[4,3]

// And now there's nothing left in arr to pass into the callback,
// because we've popped the later elements are already gone.

```

It sounds like the behavior you're expecting, is for the entire array to be duplicated when you start doing a `.forEach()`, and then you iterate over this hidden duplicate array while mutating the original. But, this sounds incredibly inefficient - I don't know of any languages that do this sort of thing.

---

<div class="post-metadata">

**Author:** ![amkmishra](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@amkmishra](https://es.discourse.group/u/amkmishra)\
**Post date:** [January 25, 2022, 2:23am UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/4 "2022-01-25T02:23:33Z")

</div>

forEach means that for each element it will be iterated doesn't matter the array length, so more like a copy of the array which will iterate through all elements.

have seen differences of forEach behaviour between v92 and v97 of chrome browser.

---

<div class="post-metadata">

**Author:** ![amkmishra](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@amkmishra](https://es.discourse.group/u/amkmishra)\
**Post date:** [January 25, 2022, 2:32am UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/5 "2022-01-25T02:32:15Z")

</div>

Versions of browsers, let's say chrome.  
Well, the one possible way is that you keep a copy of the arr and iterate over it, but if another element is being removed it won't reflect, so associated copies of array elements is the only way.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [January 25, 2022, 2:38am UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/6 "2022-01-25T02:38:41Z")

</div>

There's no way for it to prevent mutation. It's not about the length, it's that if it's on the, say, second item, and you unshift one to the front, should forEach visit it, or not? If you pop one off the back, should forEach visit it, or not?

The language has made choices about these, whether your agree with them or not is immaterial.

The main thing is that it makes no sense to mutate something you're midway iterating on, and if you are, you probably should be building your own iteration abstraction (with a for loop, perhaps) rather than relying on one that assumes the common case of not changing your horse midstream.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [January 25, 2022, 2:43am UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/7 "2022-01-25T02:43:50Z")

</div>

or, you make a copy instead of mutating it - ie, `arr.map`, or `arr.reduce`, or something.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [January 25, 2022, 3:58am UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/8 "2022-01-25T03:58:39Z")

</div>

@amkmishra - I just tested your code snippet on Chrome v92, and it showed the values `10,9,8,7,6`

 ![image](https://global.discourse-cdn.com/free1/uploads/es/original/2X/9/9208e40022c1165b924e9a778c930f62ce6ac594.png)

Specifically, I put this in a webpage, and loaded it within chrome 92:

```html
<html>
  <body>
    <script>
let arr=[1,2,3,4,5,6,7,8,9,10];
let array=[];
arr.forEach(function(a,b,c){array.push(arr.pop())},this);
console.log(array);
document.write(String(array));
    </script>
  </body>
</html>

```

---

<div class="post-metadata">

**Author:** ![amkmishra](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@amkmishra](https://es.discourse.group/u/amkmishra)\
**Post date:** [January 25, 2022, 4:37am UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/9 "2022-01-25T04:37:17Z")

</div>

May be some issue with my chrome then, showing non deterministic behaviour probably.

 ![Screenshot_20220125-095412](https://global.discourse-cdn.com/free1/uploads/es/original/2X/c/ccaed3f4a7883c2392193976db6ac7e6e41497df.jpeg)

Kidding.

---

<div class="post-metadata">

**Author:** ![amkmishra](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@amkmishra](https://es.discourse.group/u/amkmishra)\
**Post date:** [January 25, 2022, 4:54am UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/10 "2022-01-25T04:54:16Z")

</div>

By the way I would really like to have a way to create copies of array that can mutate the original array only for the elements it was copied with, but it will become another DS probably.

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [January 25, 2022, 8:07pm UTC](https://es.discourse.group/t/array-foreach-doesnt-iterate-through-all-elements-of-mutating-array/1176/11 "2022-01-25T20:07:26Z")

</div>

> [@amkmishra](#):
>
> May be some issue with my chrome then, showing non deterministic behaviour probably.

It's not non-deterministic, you get the same result each time.

Your issue is that you've put the `forEach` call in yet another loop in your screenshot, completely messing with any reasoning. Just don't write code like that. The following might help you to understand what's going on in the code:

```js
const arr = [1,2,3,4,5,6,7,8,9,10];
const array = [];
for (let i=0; i<arr.length; i++) {
    arr.forEach((_, j) => {
        console.log(i, j, JSON.stringify(arr), JSON.stringify(array));
        array.push(arr.pop());
    });
    console.log(i, arr.length, 'stopped')
}
console.log(arr.length, 'stopped')
console.log(JSON.stringify(arr), JSON.stringify(array));

```

Not sure what you were trying to achieve originally, maybe something like this?

```js
const arr = [1,2,3,4,5,6,7,8,9,10];
const array = arr.slice().reverse();
console.log(array);

```
