1

I have a problem with arrays in JavaScript and manipulating them inside a function.
This is an exercise from the book Eloquent JavaScript. It is about two functions:

  • reverseArray(): returns a new array which is the reverse of the argument array.
  • reverseArrayInPlace(): just reverses the argument array itself.

Inside reverseArrayInPlace(), I just called reverseArray() to create a new array and reassign to the argument of reverserArrayInPlace(). However, when I get to display the passed array, the reassignment is not reflected to the array passed.
I thought arrays in JavaScript are always passed by reference?

I have also tried to reassign an array variable to another array and it was successful if done outside a function. What could be the problem?
By the way, the exercise forbids the use of the reverse() method in JavaScript.

function reverseArray(array) {
  var new_array = [];
  for (var i = array.length-1; i >= 0; i--)
    new_array.push(array[i]);
  return new_array;
}

function reverseArrayInPlace(array) {
  array = reverseArray(array);
}
 
var r1 = [1,2,3,4,5,6,7,8,9,10];

console.log("r1 ", r1.join(",")); 
// → 1,2,3,4,5,6,7,8,9,10

console.log("reverse of r1 ", reverseArray(r1).join(","));
// → 10,9,8,7,6,5,4,3,2,1

console.log("r1 ", r1.join(","));
// → 1,2,3,4,5,6,7,8,9,10

reverseArrayInPlace(r1);
// the changes are not reflected here

console.log("r1 reversed in place ", r1.join(",")); 
// → still 1,2,3,4,5,6,7,8,9,10;
// this should display r1 = 10,9,8,7,6,5,4,3,2,1
theAlexandrian
  • 870
  • 6
  • 18
Ariel Catli
  • 43
  • 1
  • 4
  • 2
    JavaScript **only** has Pass-By-Value (which still allows [Call-By-Object-Sharing](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing)). Please search and clear up this confusion *before* using the tag 'Pass-By-Reference'. – user2864740 Feb 20 '18 at 02:21
  • 1
    Anyway, the changes "are not reflected" because the supplied object *is not mutated* (and assigning to the parameter has *no effect in the caller* because JavaScript *only* has Pass-By-Value; see above.) – user2864740 Feb 20 '18 at 02:23
  • 2
    `reverseArray` returns a new array ... `array = reverseArray(array);` assigns the *local* (the argument) reference to the array to this new array, thereby breaking the reference to the passed in array, but does not change the passed in array, because, well, it doesn't – Jaromanda X Feb 20 '18 at 02:23
  • to be fair, @user2864740 ... who wants to say `pass-by-value a reference to an object` :p – Jaromanda X Feb 20 '18 at 02:26
  • @JaromandaX This is why I say "Call by Object Sharing". It conveys the expected behavior/semantics and avoids the entire notion of a 'reference' - which is *not* defined in ECMAScript as a "reference to an object" and is defined differently (or still not at all) in other languages :} – user2864740 Feb 20 '18 at 02:30
  • Possible duplicate of [Is JavaScript a pass-by-reference or pass-by-value language?](https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language) – Herohtar Feb 20 '18 at 02:39
  • Well, I still have a way to go. The book didn't explained these very well (as of now) and it inserted the exercise to let us have some questions for ourselves. Thank you all for this help! – Ariel Catli Feb 20 '18 at 23:57

1 Answers1

2

The variable array of your function reverseArrayInPlace is local to that function. Thus, assigning to it just makes the scope forget about the previous value which was the array r1.

Consider the following :

var a = 5;
function change(a) {
  // Inner 'a'
  a = 0;
  console.log("inside change : ", a);
}

// Outer 'a'
change(a); // → 0
console.log("outside change : ", a); // → 5

You can see that although both the global scope and change's scope use the same name a, they are not the same variables. Assigning to a inside change will never affect the outer a.

HOWEVER
For an object (or everything that's an instance of Object.prototype, like an array), changing the properties inside a function will effectively change it outside.

To fully understand this, look at the following carefully :

var o = {
  arr1: [1, 2, 3],
  arr2: [1, 2, 3],
  str: "foo",
  num: 1
};

console.log("before changing : ", o);

function change(a) {
  // Reassigning to properties of 'a'
  a.arr1[0] = 0;
  a.arr2 = [ "destroyed" ];
  a.str += " bar";
  a.num = a.num * 15;
  
  // Reassigning to 'a'
  a = { change: "Destroyed !" };
  
  console.log("inside change : ", a);
}


change(o); // → { change: "Destroyed !" }
console.log("outside change : ", o); // → initial 'o' with modified properties.

Assigning to a = { change: "Destroyed !" }; still did not affect o. But all the changes to o's properties were applied.

As you can see, the final result of changing o gives :

{
  arr1: [0, 1, 3],     // First item changed.
  arr2: ["destroyed"], // It's a completely new array.
  str: "foo bar",      // " bar" was added.
  num: 15              // 1 * 15
}
theAlexandrian
  • 870
  • 6
  • 18
  • you're welcome. Don't forget marking the question "answered" :) – theAlexandrian Feb 20 '18 at 08:12
  • I still didn't understand how this behaviour happens? Why does JavaScript treat the variable `a` as a separate variable only during re-assignment, but not so when we change `a` individual properties? – Purnima Aug 10 '20 at 07:14
  • Can anyone explain why `a = { change: "Destroyed !" }` doesn't update the value of `a` outside the function. How come you can only reassign properties? – Stanleyy Nov 30 '22 at 13:12