Is JavaScript a pass-by-reference or pass-by-value language?
It's interesting in JavaScript. Consider this example:
function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
This produces the output:
10
changed
unchanged
- If
obj1
was not a reference at all, then changingobj1.item
would have no effect on theobj1
outside of the function. - If the argument was a proper reference, then everything would have changed.
num
would be100
, andobj2.item
would read"changed"
. Instead,num
stays10
andobj2.item
remains"unchanged
".
Instead, the situation is that the item passed in is passed by value. But the item that is passed by value is itself a reference. Technically, this is called call-by-sharing.
In practical terms, this means that if you change the parameter itself (as with num
and obj2
), that won't affect the item that was fed into the parameter. But if you change the internals of the parameter, that will propagate back up (as with obj1
).
It's always pass by value, but for objects the value of the variable is a reference. Because of this, when you pass an object and change its members, those changes persist outside of the function. This makes it look like pass by reference. But if you actually change the value of the object variable you will see that the change does not persist, proving it's really pass by value.
Example:
function changeObject(x) {
x = { member: "bar" };
console.log("in changeObject: " + x.member);
}
function changeMember(x) {
x.member = "bar";
console.log("in changeMember: " + x.member);
}
var x = { member: "foo" };
console.log("before changeObject: " + x.member);
changeObject(x);
console.log("after changeObject: " + x.member); /* change did not persist */
console.log("before changeMember: " + x.member);
changeMember(x);
console.log("after changeMember: " + x.member); /* change persists */
Output:
before changeObject: foo
in changeObject: bar
after changeObject: foo
before changeMember: foo
in changeMember: bar
after changeMember: bar
The variable doesn't "hold" the object; it holds a reference. You can assign that reference to another variable, and now both reference the same object. It's always pass by value (even when that value is a reference...).
There's no way to alter the value held by a variable passed as a parameter, which would be possible if JavaScript supported passing by reference.