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

7
  • 2
    JavaScript only has Pass-By-Value (which still allows Call-By-Object-Sharing). Please search and clear up this confusion before using the tag 'Pass-By-Reference'. Commented Feb 20, 2018 at 2: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.) Commented Feb 20, 2018 at 2: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 Commented Feb 20, 2018 at 2:23
  • to be fair, @user2864740 ... who wants to say pass-by-value a reference to an object :p Commented Feb 20, 2018 at 2: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 :} Commented Feb 20, 2018 at 2:30

1 Answer 1

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
}
Sign up to request clarification or add additional context in comments.

3 Comments

you're welcome. Don't forget marking the question "answered" :)
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?
Can anyone explain why a = { change: "Destroyed !" } doesn't update the value of a outside the function. How come you can only reassign properties?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.