2

I have two function that accept an array as parameter, these function do a simple work, making all element of the array to zero.

First function using forEach() method and passing a callback to it:

function pass_arr(x)
{
  x.forEach(function(y){
    y = 0;
  });
}

And I call it this way:

var a = ["a", "b", 1, 3, "stringg"];
pass_arr(a);

Then printing the content of array a:

for(var i = 0; i < a.length; i++)
{
  console.log(a[i]);
}

I execute this using node:

#nodejs func.js

and got the result

a
b  
1
3
stringg

Second function using normal function call :

function pass_arr(x)
{  
  for(var i = 0; i < a.length; i++)
  {
    x[i] = 0;
  }
}

var a = ["a", "b", 1, 3, "stringg"];
pass_arr(a);
for(var i = 0; i < a.length; i++)
{
   console.log(a[i]);
}

#node func.js

And got the result :

0
0
0
0
0

As far as i know when we pass an array to a function, then we dopass by referenceand thus we can modify the content of the array inside the function.

My question is why the first function doesn't properly zeroing the content of the array? Please give some clear explanation?

Lundu Harianja
  • 443
  • 1
  • 9
  • 17
  • Yes, they're passed by reference *(or more accurately, a reference to the array gets passed by value)*, but that's just for object types. When you're in the `.forEach()` callback, you're getting passed each primitive value in the Array. Those have no reference semantics at all. –  Jun 28 '15 at 22:40

4 Answers4

0

In this block of code:

function pass_arr(x)
{
  x.forEach(function(y){
    y = 0;
  });
}

y is just an argument to the callback (it is separate from the actual array item), so assigning to it just changes the value of the argument. It has no effect on the array.

If you want to modify the array, you will have to reference the array:

function pass_arr(x)
{
  x.forEach(function(y, index, array){
    array[index] = 0;
  });
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

You're assigning 0 to the value. Use the index (i, here) to replace the actual element.

Try it:

function pass_arr(x) {
    x.forEach(function (value, i) {
        x[i] = 0;
    });
}

var a = ["a", "b", 1, 3, "stringg"];
pass_arr(a);

console.log(a.join("\n"));
blex
  • 24,941
  • 5
  • 39
  • 72
0

x points to the same array, so using x[i] = will write to the ith element of x. When you use .forEach, y the argument to the callback is a primitive in the case of your array. If you write to a primitive, it will not alter the original array. That is to say you cannot use .forEach to alter the original array by writing to primitives. However, you can still alter the original array in the same way:

x.forEach((y, idx) => x[idx] = 0);

This is somewhat unrelated, but a way to do this would be to use .map.

x = ["a", "b", 1, 3, "stringg"].map(function (y) { return 0; });

I want to point out that in multi dimensional arrays, the argument taken by the callback is not a copy of the array element but will point to the original element.

let x = [[0]];
x.forEach(y => y[0] = 1);
// x is now [[1]]

Also note that JavaScript (as well as Java and many other languages) are not pass-by-reference langauges. All arguments are passed by value -- it's just that objects and arrays are stored in variables by references that are themselves passed. This is what allows you to mutate their properties in functions.

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
0

The first function is equivalent to this:

for(var i = 0; i < a.length; i++)
  {
    y = x[i];
    y = 0;
  }
}

So y is being overwritten as a separate variable.

You can use the index parameter of forEach to get the expected behavior:

x.forEach(function(y, index, arr){
  arr[index] = 0;
});

Either way, you must assign 0 to array[i], not to a separate variable holding the value of array[i]

Tyler Eich
  • 4,239
  • 3
  • 21
  • 45