Is JavaScript a pass-by-reference or pass-by-value language?

Viewed 494781

The primitive types (number, string, etc.) are passed by value, but objects are unknown, because they can be both passed-by-value (in case we consider that a variable holding an object is in fact a reference to the object) and passed-by-reference (when we consider that the variable to the object holds the object itself).

Although it doesn't really matter at the end, I want to know what is the correct way to present the arguments passing conventions. Is there an excerpt from JavaScript specification, which defines what should be the semantics regarding this?

33 Answers

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.

JavaScript is always pass-by-value; everything is of value type.

Objects are values, and member functions of objects are values themselves (remember that functions are first-class objects in JavaScript). Also, regarding the concept that everything in JavaScript is an object; this is wrong. Strings, symbols, numbers, booleans, nulls, and undefineds are primitives.

On occasion they can leverage some member functions and properties inherited from their base prototypes, but this is only for convenience. It does not mean that they are objects themselves. Try the following for reference:

x = "test";
console.log(x.foo);
x.foo = 12;
console.log(x.foo);

In both console.log you will find the value to be undefined.

well, it's about 'performance' and 'speed' and in the simple word 'memory management' in a programming language.

in javascript we can put values in two layer: type1-objects and type2-all other types of value such as string & boolean & etc

if you imagine memory as below squares which in every one of them just one type2-value can be saved:

enter image description here

every type2-value (green) is a single square while a type1-value (blue) is a group of them:

enter image description here

the point is that if you want to indicate a type2-value, the address is plain but if you want to do the same thing for type1-value that's not easy at all! :

enter image description here

and in a more complicated story:

enter image description here

so here references can rescue us:
enter image description here

while the green arrow here is a typical variable, the purple one is an object variable, so because the green arrow(typical variable) has just one task (and that is indicating a typical value) we don't need to separate it's value from it so we move the green arrow with the value of that wherever it goes and in all assignments, functions and so on ...

but we cant do the same thing with the purple arrow, we may want to move 'john' cell here or many other things..., so the purple arrow will stick to its place and just typical arrows that were assigned to it will move ...

a very confusing situation is where you can't realize how your referenced variable changes, let's take a look at a very good example:

let arr = [1, 2, 3, 4, 5]; //arr is an object now and a purple arrow is indicating it
let obj2 = arr; // now, obj2 is another purple arrow that is indicating the value of arr obj
let obj3 = ['a', 'b', 'c'];
obj2.push(6); // first pic below - making a new hand for the blue circle to point the 6
//obj2 = [1, 2, 3, 4, 5, 6]
//arr = [1, 2, 3, 4, 5, 6]
//we changed the blue circle object value (type1-value) and due to arr and obj2 are indicating that so both of them changed
obj2 = obj3; //next pic below - changing the direction of obj2 array from blue circle to orange circle so obj2 is no more [1,2,3,4,5,6] and it's no more about changing anything in it but we completely changed its direction and now obj2 is pointing to obj3
//obj2 = ['a', 'b', 'c'];
//obj3 = ['a', 'b', 'c'];

enter image description here enter image description here

This is little more explanation for pass by value and pass by reference (JavaScript). In this concept, they are talking about passing the variable by reference and passing the variable by reference.

Pass by value (primitive type)

var a = 3;
var b = a;

console.log(a); // a = 3
console.log(b); // b = 3

a=4;
console.log(a); // a = 4
console.log(b); // b = 3
  • applies to all primitive type in JavaScript (string, number, Boolean, undefined, and null).
  • a is allocated a memory (say 0x001) and b creates a copy of the value in memory (say 0x002).
  • So changing the value of a variable doesn't affect the other, as they both reside in two different locations.

Pass by reference (objects)

var c = { "name" : "john" };
var d = c;

console.log(c); // { "name" : "john" }
console.log(d); // { "name" : "john" }

c.name = "doe";

console.log(c); // { "name" : "doe" }
console.log(d); // { "name" : "doe" }
  • The JavaScript engine assigns the object to the variable c, and it points to some memory, say (0x012).
  • When d=c, in this step d points to the same location (0x012).
  • Changing the value of any changes value for both the variable.
  • Functions are objects

Special case, pass by reference (objects)

c = {"name" : "jane"};
console.log(c); // { "name" : "jane" }
console.log(d); // { "name" : "doe" }
  • The equal(=) operator sets up new memory space or address

Observation: If there isn't any way for an observer to examine the underlying memory of the engine, there is no way to determine whether an immutable value gets copied or a reference gets passed.

JavaScript is more or less agnostic to the underlying memory model. There is no such thing as a reference². JavaScript has values. Two variables can hold the same value (or more accurate: two environment records can bind the same value). The only type of values that can be mutated are objects through their abstract [[Get]] and [[Set]] operations. If you forget about computers and memory, this is all you need to describe JavaScript's behaviour, and it allows you to understand the specification.

 let a = { prop: 1 };
 let b = a; // a and b hold the same value
 a.prop = "test"; // The object gets mutated, can be observed through both a and b
 b = { prop: 2 }; // b holds now a different value

Now you might ask yourself how two variables can hold the same value on a computer. You might then look into the source code of a JavaScript engine and you'll most likely find something which a programmer of the language the engine was written in would call a reference.

So in fact you can say that JavaScript is "pass by value", whereas the value can be shared, and you can say that JavaScript is "pass by reference", which might be a useful logical abstraction for programmers from low level languages, or you might call the behaviour "call by sharing".

As there is no such thing as a reference in JavaScript, all of these are neither wrong nor on point. Therefore I don't think the answer is particularly useful to search for.

² The term Reference in the specification is not a reference in the traditional sense. It is a container for an object and the name of a property, and it is an intermediate value (e.g., a.b evaluates to Reference { value = a, name = "b" }). The term reference also sometimes appears in the specification in unrelated sections.

Everything is passed by value.

Basic types are passed by value (i.e. a new copy of the actual variable value is passed to the function).

Complex types (objects) are passed as "pointer to the object". So the actual stuff you are passing is a pointer which is passed by value (it's an address, a numerical value like any other). Obviously if you try to modify a property of the object inside the function, the modification will be reflected even outside of such function. That's because you are accessing the property via the pointer which points to the unique copy of the property.

The confusion here has arises over "passing a pointer by value" and "passing an object by reference".

JavaScript passes primitive types by value and object types by reference

Now, people like to bicker endlessly about whether "pass by reference" is the correct way to describe what Java et al. actually do. The point is this:

  1. Passing an object does not copy the object.
  2. An object passed to a function can have its members modified by the function.
  3. A primitive value passed to a function cannot be modified by the function. A copy is made.

In my book that's called passing by reference.

Brian Bi - Which programming languages are pass by reference?


Update

Here is a rebuttal to this:

There is no "pass by reference" available in JavaScript.

The MDN docs explain it clearly, without being too verbose:

The parameters of a function call are the function's arguments. Arguments are passed to functions by value. If the function changes the value of an argument, this change is not reflected globally or in the calling function. However, object references are values, too, and they are special: if the function changes the referred object's properties, that change is visible outside the function, (...)

Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Description

In a low-level language, if you want to pass a variable by reference, you have to use a specific syntax in the creation of the function:

int myAge = 14;
increaseAgeByRef(myAge);
function increaseAgeByRef(int &age) {
  *age = *age + 1;
}

The &age is a reference to myAge, but if you want the value you have to convert the reference, using *age.

JavaScript is a high level language that does this conversion for you.

So, although objects are passed by reference, the language converts the reference parameter to the value. You don't need to use &, on the function definition, to pass it by reference, neither *, on the function body, to convert the reference to the value, JavaScript does it for you.

That's why when you try to change an object inside a function, by replacing it's value (i.e. age = {value:5}), the change doesn't persist, but if you change it's properties (i.e. age.value = 5), it does.

Learn more

If you want (normal) function parameter behavior like in other languages (passing copy of a value) then just clone the object before passing into a function:

function run()
{
    var test = [];
    test.push(1);

    console.log('before: '+test); // 1

    changeVariable(_.clone(test)); // (Note: I am using lodash _.clone() function)
 
    console.log('after: '+test); // 1 
}


function changeVariable(test2) {
  var test1 = test2;
  test1.push(2); 
  console.log('inside func:', test1);  // inside func: [1,2]
}   


run();    

An easy way to determine whether something is "pass by reference" is whether you can write a "swap" function. For example, in C, you can do:

void swap(int *i, int *j)
{
    int t;
    t = *i;
    *i = *j;
    *j = t;
}

If you can't do the equivalent of that in JavaScript, it is not "pass by reference".

There's some discussion about the use of the term "pass by reference" in JavaScript here, but to answer your question:

A object is automatically passed by reference, without the need to specifically state it

(From the article mentioned above.)

Related