change values in array when doing foreach
example:
var arr = ["one","two","three"];
arr.forEach(function(part){
part = "four";
return "four";
})
alert(arr);
The array is still with it's original values, is there any way to have writing access to array's elements from iterating function ?
Solution 1:
The callback is passed the element, the index, and the array itself.
arr.forEach(function(part, index, theArray) {
theArray[index] = "hello world";
});
edit — as noted in a comment, the .forEach()
function can take a second argument, which will be used as the value of this
in each call to the callback:
arr.forEach(function(part, index) {
this[index] = "hello world";
}, arr); // use arr as this
That second example shows arr
itself being set up as this
in the callback.One might think that the array involved in the .forEach()
call might be the default value of this
, but for whatever reason it's not; this
will be undefined
if that second argument is not provided.
(Note: the above stuff about this
does not apply if the callback is a =>
function, because this
is never bound to anything when such functions are invoked.)
Also it's important to remember that there is a whole family of similar utilities provided on the Array prototype, and many questions pop up on Stackoverflow about one function or another such that the best solution is to simply pick a different tool. You've got:
-
forEach
for doing a thing with or to every entry in an array; -
filter
for producing a new array containing only qualifying entries; -
map
for making a one-to-one new array by transforming an existing array; -
some
to check whether at least one element in an array fits some description; -
every
to check whether all entries in an array match a description; -
find
to look for a value in an array
and so on. MDN link
Solution 2:
Let's try to keep it simple and discuss how it is actually working. It has to do with variable types and function parameters.
Here is your code we are talking about:
var arr = ["one","two","three"];
arr.forEach(function(part) {
part = "four";
return "four";
})
alert(arr);
First off, here is where you should be reading about Array.prototype.forEach():
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Second, let's talk briefly about value types in JavaScript.
Primitives (undefined, null, String, Boolean, Number) store an actual value.
ex: var x = 5;
Reference Types (custom objects) store the memory location of the object.
ex: var xObj = { x : 5 };
And third, how function parameters work.
In functions, parameters are always passed by value.
Because arr
is an array of Strings, it's an array of primitive objects, which means they are stored by value.
So for your code above, this means that each time the forEach() iterates, part
is equal to the same value as arr[index]
, but not the same object.
part = "four";
will change the part
variable, but will leave arr
alone.
The following code will change the values you desire:
var arr = ["one","two","three"];
arr.forEach(function(part, index) {
arr[index] = "four";
});
alert(arr);
Now if array arr
was an array of reference types, the following code will work because reference types store a memory location of an object instead of the actual object.
var arr = [{ num : "one" }, { num : "two"}, { num : "three"}];
arr.forEach(function(part, index) {
// part and arr[index] point to the same object
// so changing the object that part points to changes the object that arr[index] points to
part.num = "four";
});
alert(arr[0].num);
alert(arr[1].num);
alert(arr[2].num);
The following illustrates that you can change part
to point to a new object while leaving the objects stored in arr
alone:
var arr = [{ num : "one" }, { num : "two"}, { num : "three"}];
arr.forEach(function(part, index) {
// the following will not change the object that arr[index] points to because part now points at a new object
part = 5;
});
alert(arr[0].num);
alert(arr[1].num);
alert(arr[2].num);