JavaScript by reference vs. by value

324,195

Solution 1

My understanding is that this is actually very simple:

  • Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
  • Changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.
  • However, changing a property of an object referenced by a variable does change the underlying object.

So, to work through some of your examples:

function f(a,b,c) {
    // Argument a is re-assigned to a new value.
    // The object or primitive referenced by the original a is unchanged.
    a = 3;
    // Calling b.push changes its properties - it adds
    // a new property b[b.length] with the value "foo".
    // So the object referenced by b has been changed.
    b.push("foo");
    // The "first" property of argument c has been changed.
    // So the object referenced by c has been changed (unless c is a primitive)
    c.first = false;
}

var x = 4;
var y = ["eeny", "miny", "mo"];
var z = {first: true};
f(x,y,z);
console.log(x, y, z.first); // 4, ["eeny", "miny", "mo", "foo"], false

Example 2:

var a = ["1", "2", {foo:"bar"}];
var b = a[1]; // b is now "2";
var c = a[2]; // c now references {foo:"bar"}
a[1] = "4";   // a is now ["1", "4", {foo:"bar"}]; b still has the value
              // it had at the time of assignment
a[2] = "5";   // a is now ["1", "4", "5"]; c still has the value
              // it had at the time of assignment, i.e. a reference to
              // the object {foo:"bar"}
console.log(b, c.foo); // "2" "bar"

Solution 2

Javascript always passes by value. However, if you pass an object to a function, the "value" is really a reference to that object, so the function can modify that object's properties but not cause the variable outside the function to point to some other object.

An example:

function changeParam(x, y, z) {
  x = 3;
  y = "new string";
  z["key2"] = "new";
  z["key3"] = "newer";

  z = {"new" : "object"};
}

var a = 1,
    b = "something",
    c = {"key1" : "whatever", "key2" : "original value"};

changeParam(a, b, c);

// at this point a is still 1
// b is still "something"
// c still points to the same object but its properties have been updated
// so it is now {"key1" : "whatever", "key2" : "new", "key3" : "newer"}
// c definitely doesn't point to the new object created as the last line
// of the function with z = ...

Solution 3

Yes, Javascript always passes by value, but in an array or object, the value is a reference to it, so you can 'change' the contents.

But, I think you already read it on SO; here you have the documentation you want:

http://snook.ca/archives/javascript/javascript_pass

Solution 4

  1. Primitive type variable like string,number are always pass as pass by value.
  2. Array and Object is passed as pass by reference or pass by value based on these two condition.

    • if you are changing value of that Object or array with new Object or Array then it is pass by Value.

      object1 = {item: "car"}; array1=[1,2,3];

    here you are assigning new object or array to old one.you are not changing the value of property of old object.so it is pass by value.

    • if you are changing a property value of an object or array then it is pass by Reference.

      object1.item= "car"; array1[0]=9;

    here you are changing a property value of old object.you are not assigning new object or array to old one.so it is pass by reference.

Code

    function passVar(object1, object2, number1) {

        object1.key1= "laptop";
        object2 = {
            key2: "computer"
        };
        number1 = number1 + 1;
    }

    var object1 = {
        key1: "car"
    };
    var object2 = {
        key2: "bike"
    };
    var number1 = 10;

    passVar(object1, object2, number1);
    console.log(object1.key1);
    console.log(object2.key2);
    console.log(number1);

Output: -
    laptop
    bike
    10
Share:
324,195
jfriend00
Author by

jfriend00

25 years of software coding and management. Now, retired.

Updated on July 08, 2022

Comments

  • jfriend00
    jfriend00 almost 2 years

    I'm looking for some good comprehensive reading material on when JavaScript passes something by value and when by reference and when modifying a passed item affects the value outside a function and when not. I'm also interested in when assigning to another variable is by reference vs. by value and whether that follows any different rules than passing as a function parameter.

    I've done a lot of searching and find lots of specific examples (many of them here on SO) from which I can start to piece together pieces of the real rules, but I haven't yet found a single, well written document that describes it all.

    Also, are there ways in the language to control whether something is passed by reference or by value?

    Here are some of the types of questions I want to understand. These are just examples - I'm actually looking to understand the rules the language goes by, not just the answers to specific examples. But, here are some examples:

    function f(a,b,c) {
       a = 3;
       b.push("foo");
       c.first = false;
    }
    
    var x = 4;
    var y = ["eeny", "miny", "mo"];
    var z = {first: true};
    f(x,y,z);
    

    When are the contents of x, y and z changed outside the scope of f for all the different types?

    function f() {
        var a = ["1", "2", "3"];
        var b = a[1];
        a[1] = "4";
        // what is the value of b now for all possible data types that the array in "a" might hold?
    }
    
    function f() {
        var a = [{yellow: "blue"}, {red: "cyan"}, {green: "magenta"}];
        var b = a[1];
        a[1].red = "tan";
        // what is the value of b now and why?
        b.red = "black";
        // did the value of a[1].red change when I assigned to b.red?
    }
    

    If I want to make a fully independent copy of an object (no references whatsoever), what's the best practice way to do that?

  • Admin
    Admin almost 13 years
    While technically true, I prefer to say JavaScript is Pass By Object Sharing. It avoids such confusion and moves to a "high level" view.
  • Admin
    Admin almost 13 years
    While technically true, I prefer to say JavaScript is Pass By Object Sharing. It avoids such confusion and moves to a "high level" view.
  • nrabinowitz
    nrabinowitz almost 13 years
    @pst - That makes sense, but note the issues raised in the referenced Wikipedia page - most people don't use the term, and the (large) Java community calls this "pass-by-value". Still, I agree that it's a bit confusing.
  • tkane2000
    tkane2000 about 10 years
    I made a fiddle to play around with this a bit: jsfiddle.net/tkane2000/7weKS/1
  • MEMark
    MEMark almost 10 years
    What "confusion" are you referring to? To me "pass-by-value" is perfectly clear.
  • Dan Dascalescu
    Dan Dascalescu over 9 years
    The example in this question that this one duplicates, shows an even more interesting case: c = {first: '5'}. After executing f(x, y, z), z will remain {first: true}.
  • newacct
    newacct over 9 years
    Nope. Everything is pass by value, always.
  • Mukund Kumar
    Mukund Kumar over 9 years
    just put above code in your console and see...value got change..
  • jfriend00
    jfriend00 over 9 years
    There's a time honored terminology debate about calling what Javascript does "pass by reference". I prefer to side step that debate and call what JS does for objects and arrays "pass by pointer". Arrays and Objects are always pass by pointer. If you modify what was passed in (accessing the pointer), the original is modified. If you assign a different array or object to the pointer variable, then the original is not modified because your variable now "points" to a different array or object. Much of this is a "terminology debate", because there is no debate about what actually happens.
  • jfriend00
    jfriend00 over 9 years
    @newacct - And for those that like to claim "everything is pass by value", that doesn't help newbies understand the issue in any way no matter how technically correct you might think you are at some level. Any good explanation has to explain the difference between how objects and primitives are passed such that a newbie understands the difference in practical use since the goal in a question and answer like this is a clear explanation that can be put to use for those who don't understand the finer implementation details or technical meaning of terms.
  • newacct
    newacct over 9 years
    @jfriend00: The thing is, there is nothing special about "passing". It works the same way as assigning or any other operation. Once you understand that all values are either primitives or pointers to objects, and not talk about "objects" as values themselves, then there is no confusion. Also, the semantics of passing and assigning in JavaScript are identical to those in Java. And "everything is pass by value" is pretty much how Java is generally described on StackOverflow, combined with explanation how all non-primitives are pointers to objects.
  • jfriend00
    jfriend00 over 9 years
    @newacct - the point here is to explain to people who aren't sophisticated developers and saying everything is "pass by value" without a lot more explanation just simply isn't enough. It doesn't explain the difference in how a primitive and an array are passed or assigned. You can argue it's technically correct, but it's an insufficient explanation for non-sophisticated developers. Your very comment that "once you understand ..." shows that it isn't sufficient until you understand other things - thus you can't just say "everything is pass by value" to a newbie and be done.
  • newacct
    newacct over 9 years
    @jfriend00: But I am not answering a question here. I am commenting on a statement made in an answer. If I were writing an answer it would have much content. But here I am just simply pointing out the statement I think is wrong without including tons of stuff which may get off topic.
  • Amit Tomar
    Amit Tomar over 8 years
    Changing the value of a variable never changes the underlying primitive or object. However, changing a property of an object referenced by a variable does change the underlying object. These two sentences put together remove so many doubts. Thank you!
  • shyammakwana.me
    shyammakwana.me about 8 years
    Array is a object so will change also.
  • Rafael
    Rafael about 8 years
    coming from c, this is stupid and annoying, state state state...
  • ralixyle
    ralixyle almost 7 years
    var users = [1,2,3,4]; var x_users = users; x_users.push(5); now users and x_users are the same since it's passed by reference. One way to fix this would be var x_users = users.slice(0); x_users.push(6); now users and x_users are different since x_users is not referring to users. Took me a while to figure it out :-) Hope this may help someone.
  • StanE
    StanE over 6 years
    Which is funny, because in JavaScript everything is considered to be an object... ['hi','ho'].length, (4).toString(), 'Hi'.length
  • doubleOrt
    doubleOrt over 6 years
    So, all JavaScript primitives are immutable, and all values are "by sharing" (as stated by @user166390). So, for primitives, it does not matter at all, but I assume passing everything by reference is more efficient performance-wise (since stuff isn't copied over everytime), and objects are obviously not duplicated during an assignment, could we then state that "everything in JavaScript is by reference" (or "by sharing") ? I know it is the exact opposite of what you state, but the concept is essentially the same and this seems more true given that primitives are immutable.
  • doubleOrt
    doubleOrt over 6 years
    continuing see this Wikipedia page which states that all JavaScript values are reference types (and take a peek at the spec source for that statement as well). But then, how can this coexist with the fact that sometimes values are stored in the stack not the heap ?
  • Hritik
    Hritik over 5 years
    Coming from C, it seems in all calls pointers to a certain memory (object) are passed.
  • Hritik
    Hritik over 5 years
    Except nearly everything in JavaScript is an object.
  • nnnnnn
    nnnnnn over 5 years
    @Hritik - Except for all of the primitive values that are not objects.
  • JWess
    JWess over 4 years
    "pass by copy of reference" is the most accurate way to describe how non-primitives are passed into a function. This implies that the original reference variable (from outside the function) is not accessible inside the function...but a copy of this reference variable IS available. This is why the original reference variable cannot be changed from inside the function to point at a different object, but the original object's properties can be edited, because our copied reference variable is still pointing at that same object.