In JavaScript all arguments are passed by value. When a function assigns a new value to an argument variable, that change will not be visible to the caller:
var obj = {a: 2};
function myfunc(arg){
arg = {a: 5}; // Note the assignment is to the parameter variable itself
}
myfunc(obj);
console.log(obj.a); // 2
However, changes made to (nested) properties of such arguments, will be visible to the caller:
var obj = {a: 2};
function myfunc(arg){
arg.a = 5; // assignment to a property of the argument
}
myfunc(obj);
console.log(obj.a); // 5
This can be seen as a call by reference: although a function cannot change the caller's object by assigning a new value to it, it could mutate the caller's object.
As primitive valued arguments, like numbers or strings, are immutable, there is no way for a function to mutate them:
var s = 'say';
function myfunc(arg){
arg += ' hello'; // assignment to the parameter variable itself
}
myfunc(s);
console.log(s); // 'say'
When a function wants to mutate an object passed as argument, but does not want to actually mutate the caller's object, the argument variable should be reassigned:
var obj = {a: 2, b: 3};
function myfunc(arg){
arg = Object.assign({}, arg); // assignment to argument variable, shallow copy
arg.a = 5;
}
myfunc(obj);
console.log(obj.a); // 2
As an alternative to in-place mutation of an argument, functions can create a new value, based on the argument, and return it. The caller can then assign it, even to the original variable that was passed as argument:
var a = 2;
function myfunc(arg){
arg++;
return arg;
}
a = myfunc(a);
console.log(obj.a); // 3