2

I have a function that reverses an array:

function reverseArray(array) {
  for(let i = 0; i <= Math.floor(array.length / 2); i++) {
    let old = array[array.length - 1 - i];
    array[array.length - 1 - i] = array[i];
    array[i] = old;
  }
  return array;
}

and a function that creates an local scope array and push values in reversed order:

function reverseArr(arr) {
  let output = [];
  for(let i of arr) {
    output.unshift(i);
  }
  arr = output;
  return arr;
}

Suppose there is an element:

let arrayValue = [1, 2, 3, 4, 5];

If i invoke the first function with arrayValue as argument, arrayValue is changed:

reverseArray(arrayValue); // [5, 4, 3, 2, 1]
console.log(arrayValue); // [5, 4, 3, 2, 1]

However if i invoke the second function with arrayValue:

reverseArr(arrayValue); //[5, 4, 3, 2, 1]
console.log(arrayValue); //[1, 2, 3, 4, 5]

arrayValue is not changed even if i assigned the reversed value to the argument before return:

arr = output;

can someone explain me why?

thanks in advance.

Vank
  • 31
  • 5
  • 1
    I don't think `unshift` does what you think it does. Read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift. – Robert Harvey Nov 13 '20 at 19:08
  • 1
    See also [here](https://medium.com/@josephcardillo/how-to-reverse-arrays-in-javascript-without-using-reverse-ae995904efbe), which describes a better approach using `push`. – Robert Harvey Nov 13 '20 at 19:10
  • 2
    Does this answer your question? [Javascript function not modifying array (reference?)](https://stackoverflow.com/questions/33308339/javascript-function-not-modifying-array-reference) – Heretic Monkey Nov 13 '20 at 19:17
  • @RobertHarvey um.... unshift() is the correct thing to use here.... OP is reversing an array so it is appending to the front, your suggestion is adding it to the end..... So OP would get back the same array order since the loop is not going backwards.... – epascarello Nov 13 '20 at 19:17
  • @epascarello: In the example I linked, the loop *is* going backwards. – Robert Harvey Nov 13 '20 at 19:20
  • 1
    JS is *pass-by-value*, when you do `arr = output` you're only reassigning the local variable `arr`. You don't replace the array it used to reference nor do you affect the other variable (`arrayValue`) that still references that array. In your first example you're mutating that array directly. – Lennholm Nov 13 '20 at 19:25
  • @RobertHarvey Yes and OP is not looping in reverse and your first comment is wrong. – epascarello Nov 13 '20 at 19:33
  • @epascarello. Read the example I linked; it's perfectly good code. Instead of arguing with me, try using your time productively and post a proper answer. – Robert Harvey Nov 13 '20 at 19:44
  • My argument started because your very first comment in incorrect. And if OP follow the code in the link, it would still have the same issue because it does not alter the original array. – epascarello Nov 13 '20 at 20:31

3 Answers3

4

Basically you take a new array with

let output = [];

and later you assign the new array to the parameter arr

arr = output;

Now you have two object references, one arr of the outer scope and a new one of output.

To overcome this, you need to keep the object reference of array. For getting a new content in an existing array, you could empty the array and push the values of the new array.

arr.length = 0;
arr.push(...output);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

When you do arr = output in reverseArr you are referring to a new array. In other words arrayValue in the outer context and arr refer to two different objects.

You cannot change the value of the variable the function is called with. If you have a reference to the object you can mutate it, but you cannot make the outside variable refer to another object.

Vlad Saveluc
  • 116
  • 1
  • 4
1

Basically, your first function reverses the list in-place (i.e. operates on the list itself directly, without building a new list), while the second function reverses the list out-of-place, by building a new list which contents are the reverse of the original list.

When working in-place, the changes you do to array inside the function are directly applied to arrayValue.

The reason why arr = output does not work the way you intend is pretty much what the other answers refer to. Namely, arr and arrayValue are two different references ("pointers"). Initially, both arrayValue and arr "point to" the same array when the function is called. However, arr = output makes arr point to the newly built list output instead.

Anis R.
  • 6,656
  • 2
  • 15
  • 37