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
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
}