Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

forEach does not mutate an array that I pass in

Tags:

javascript

I've created a simple forEach function and I'm trying to understand why, when I run it with myArray, it doesn't mutate the array even though I run element*2.

function forEach(array, callback) {
  for (var i = 0; i < array.length; i++) {
    callback(array[i],i,array)
  };
}

var myArray = [1,2,3]
forEach(myArray,function(element){element*2})
console.log(myArray)///[1,2,3]
like image 488
Tom Brown Avatar asked May 08 '15 15:05

Tom Brown


People also ask

Does forEach mutate an array?

forEach() does not mutate the array on which it is called, but the function provided as callbackFn can.

Can forEach mutate?

No, forEach does not mutate the original array. You can achieve what you are looking for by giving a second parameter of index , then updating the values of the original array.

Does forEach modify?

The forEach method of an array does not modify the array, it just iterates over it. When you change the argument in the callback function, that doesn't affect the array either. Also, forEach doesn't do anything with the return values from the callback.

Is array forEach blocking?

forEach Asynchronous? It is not asynchronous. It is blocking.


2 Answers

You have to modify the array in the for loop, like this:

function forEach(array, callback) {
  for (var i = 0; i < array.length; i++) {
    array[i] = callback(array[i],i,array)
  };
}

var myArray = [1,2,3]
forEach(myArray,function(element){return element*2})
console.log(myArray)

As we were discussing in the comments, the best way would be to implement something like the map function: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map

function map(array, callback) {
  var out = [];
  for (var i = 0; i < array.length; i++) {
    out.push(callback(array[i],i,array))
  };

  return out;
}

var myArray = [1,2,3]
var myOtherArray = map(myArray,function(element){return element*2})
console.log(myArray)
console.log(myOtherArray)

This way myArray is not touched, you create a new one. This is usually the best option, but sometimes you may want to modify it in place, because it is huge or for some other (good?) reason. In that case you can use the first option.

like image 126
Martin E. Zulliger Avatar answered Oct 03 '22 03:10

Martin E. Zulliger


You should assign new array element value, because primitive types (like numbers in your case) are immutable, so element * 2 does not modify element.

To do the job, you should not touch you current forEach implementation, because forEach is not supposed to return values from callback (this is not map). In this case you should do something like this:

function forEach(array, callback) {
  for (var i = 0; i < array.length; i++) {
    callback(array[i], i, array);
  }
}

var myArray = [1,2,3];
forEach(myArray, function(element, i, arr) { 
  arr[i] = element * 2;
});

document.write(JSON.stringify( myArray ));
like image 38
dfsq Avatar answered Oct 03 '22 04:10

dfsq