[javascript] JavaScript by reference vs. by value

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?

This question is related to javascript reference pass-by-reference pass-by-value

The answer is


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"

  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

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


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 = ...

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to reference

Method Call Chaining; returning a pointer vs a reference? When to create variables (memory management) Reference to non-static member function must be called Cannot find reference 'xxx' in __init__.py - Python / Pycharm c++ "Incomplete type not allowed" error accessing class reference information (Circular dependency with forward declaration) C++ initial value of reference to non-const must be an lvalue Dependent DLL is not getting copied to the build output folder in Visual Studio How to write to error log file in PHP How to reference Microsoft.Office.Interop.Excel dll? Linker Error C++ "undefined reference "

Examples related to pass-by-reference

Passing an integer by reference in Python Does JavaScript pass by reference? Object passed as parameter to another class, by value or reference? change values in array when doing foreach Call-time pass-by-reference has been removed C++ pass an array by reference Passing Objects By Reference or Value in C# Pass variables by reference in JavaScript JavaScript by reference vs. by value How to do the equivalent of pass by reference for primitives in Java

Examples related to pass-by-value

Passing an integer by reference in Python Does JavaScript pass by reference? Passing Objects By Reference or Value in C# JavaScript by reference vs. by value How to pass objects to functions in C++? Are arrays in PHP copied as value or as reference to new variables, and when passed to functions? Is JavaScript a pass-by-reference or pass-by-value language? Why should I use the keyword "final" on a method parameter in Java? Pass by Reference / Value in C++ What's the difference between passing by reference vs. passing by value?