Categories
javascript pass-by-reference pass-by-value

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

1655

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?

17

  • 7

    I think you accidentally flipped your definitions of passed-by-value and passed-by-reference… “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)”

    Aug 24, 2014 at 19:25

  • 9

    Yes. Regardless of syntax, in any function call in any programming language, pass-by-reference means the data associated with the passed variable is not copied when passed to the function, and thus any modifications made by the function to the passed variable will be retained in the program after the function call terminates. Pass-by-value means the data associated with the variable is actually copied when passed to the function and any modifications made by such function to such variable will be lost when the variable goes out of scope of the function’s body when the function returns.

    Oct 29, 2014 at 11:38

  • 7

    This old question is somewhat toxic because its heavily-upvoted answer is incorrect. JavaScript is strictly pass-by-value.

    – Pointy

    Nov 28, 2015 at 0:00

  • 8

    @DanailNachev The terminology is regrettably confusing. The thing is, “pass by value” and “pass by reference” are terms that predate a lot of more modern programming language features. The words “value” and “reference” refer specifically to the parameter as it appears in the function call expression. JavaScript always evaluates each expression in a function call parameter list before calling the function, so the parameters are always values. The confusing part is that references to objects are common JavaScript values. That doesn’t make it a “pass by reference” language, however.

    – Pointy

    Dec 15, 2015 at 22:57

  • 4

    @DanailNachev “pass by reference” specifically means that if you have var x=3, y=x; f(x); alert(y === x); then function f() can make the alert report false and not true. In JavaScript, that’s not possible, so it’s not pass-by-reference. It’s good that it’s possible to pass references to modifiable objects, but that’s not what “pass by reference” means. As I said, it’s a shame that the terminology is so confusing.

    – Pointy

    Dec 15, 2015 at 23:00

586

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

14

  • 14

    @daylight: Actually, you’re wrong; if it was passed by const ref trying to do changeObject would cause an error, rather than just failing. Try assigning a new value to a const reference in C++ and the compiler rejects it. In user terms, that’s the difference between pass by value and pass by const reference.

    – deworde

    Jul 18, 2011 at 8:56


  • 5

    @daylight: It’s not constant ref. In changeObject, I’ve changed x to contain a reference to the new object. x = {member:"bar"}; is equivalent to x = new Object(); x.member = "bar"; What I’m saying is also true of C#, by the way.

    Jul 19, 2011 at 21:47

  • 3

    @daylight: For C#, you can see this from outside the function, if you use the ref keyword you can pass the reference by reference (instead of the default of passing the reference by value), and then the change to point to a new Object() will persist.

    Jul 19, 2011 at 21:55

  • 14

    @adityamenon It’s hard to answer “why”, but I would note that the designers of Java and C# made a similar choice; this isn’t just some JavaScript weirdness. Really, it’s very consistently pass-by-value, the thing that makes it confusing for people is that a value can be a reference. It’s not much different than passing a pointer around (by value) in C++ and then dereferencing it to set the members. No one would be surprised that that change persists. But because these languages abstract away the pointer and silently do the dereferencing for you, people get confused.

    Jul 28, 2013 at 11:11

  • 63

    In other words, the confusing thing here isn’t pass-by-value/pass-by-reference. Everything is pass-by-value, full stop. The confusing thing is that you cannot pass an object, nor can you store an object in a variable. Every time you think you’re doing that, you’re actually passing or storing a reference to that object. But when you go to access its members, there’s a silent dereferencing that happens, that perpetuates the fiction that your variable held the actual object.

    Jul 28, 2013 at 11:27

165

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.

6

  • 4

    This confuses me just a bit. Isn’t passing a reference pass-by-reference?

    – user3186555

    Oct 2, 2017 at 13:13

  • 10

    The author means that by passing a reference, you’re passing a reference value (another way to think of it is passing the value of the memory address). So that’s why if you redeclare the object, the original doesn’t change, because you’re creating a new object at a different memory location. If you change a property, the original object changes because you changed it at the original memory location (that was not reassigned).

    Oct 10, 2017 at 21:09

  • The phrase “passing a reference by value” seems unnecessarily confusing and redundant. When passing a reference of course some value must be passed. While technically true, it is likely the default assumption of most people that anything is passed by value unless otherwise specified. So of course a reference is passed by value unless it itself is passed by reference (kind of like a pointer to a pointer in C), but in this case Javascript doesn’t even support that so I don’t think it helps make the concept any clearer

    – geg

    Jul 2, 2020 at 0:07

  • 1

    The point of confusion with JavaScript is that it provides no choice in the matter, @geg: complex types will always be handled indirectly, simple types always directly. There’s no way to get a reference to an integer, nor prevent passing a reference to a tuple. This … Is just going to be awkward sometimes.

    – Shog9

    Jul 2, 2020 at 0:19

  • to put simply after a decade, the reference is copied by value.

    – snr

    Aug 24, 2020 at 11:05