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




vs copy (25)

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?


Answers

Think of it like this: It's always pass by value. However, the value of an object is not the object itself, but a reference to that object.

Here is an example, passing a number (a primitive type)

function changePrimitive(val) {
    // At this point there are two '10's in memory.
    // Changing one won't affect the other
    val = val * 10;
}
var x = 10;
changePrimitive(x);
// x === 10

Repeating this with an object yields different results:

function changeObject(obj) {
    // At this point there are two references (x and obj) in memory,
    // but these both point to the same object.
    // changing the object will change the underlying object that
    // x and obj both hold a reference to.
    obj.val = obj.val * 10;
}
var x = { val: 10 };
changeObject(x);
// x === { val: 100 }

One more example:

function changeObject(obj) {
    // Again there are two references (x and obj) in memory,
    // these both point to the same object.
    // now we create a completely new object and assign it.
    // obj's reference now points to the new object.
    // x's reference doesn't change.
    obj = { val: 100 };
}
var x = { val: 10 };
changeObject(x);
// x === { val: 10}

My simple way to understand this...

  • When calling a function, you are passing the content (reference or value) of the argument variables, not the the variables themselves.

    var var1 = 13;
    var var2 = { prop: 2 };
    
    //13 and var2's content (reference) are being passed here
    foo(var1, var2); 
    
  • Inside the function, parameter variables, inVar1 and inVar2, receive the contents being passed.

    function foo(inVar1, inVar2){
        //changing contents of inVar1 and inVar2 won't affect variables outside
        inVar1 = 20;
        inVar2 = { prop: 7 };
    }
    
  • Since inVar2 received the reference of { prop: 2 }, you can change the value of the object's property.

    function foo(inVar1, inVar2){
        inVar2.prop = 7; 
    }
    

Consider the following:

  1. Variables are pointers to values in memory.
  2. Reassigning a variable merely points that pointer at a new value.
  3. Reassigning a variable will never affect other variables that were pointing at that same object

So, forget about "pass by reference/value" don't get hung up on "pass by reference/value" because:

  1. The terms are only used to describe the behavior of a language, not necessarily the actual underlying implementation. As a result of this abstraction, critical details that are essential for a decent explanation are lost, which inevitably leads to the current situation where a single term doesn't adequately describe the actual behavior and supplementary info has to be provided
  2. These concepts were not originally defined with the intent of describing javascript in particular and so I don't feel compelled to use them when they only add to the confusion.

To answer your question: pointers are passed.


// code
var obj = {
    name: 'Fred',
    num: 1
};

// illustration
               'Fred'
              /
             /
(obj) ---- {}
             \
              \
               1


// code
obj.name = 'George';


// illustration
                 'Fred'


(obj) ---- {} ----- 'George'
             \
              \
               1


// code
obj = {};

// illustration
                 'Fred'


(obj)      {} ----- 'George'
  |          \
  |           \
 { }            1


// code
var obj = {
    text: 'Hello world!'
};

/* function parameters get their own pointer to 
 * the arguments that are passed in, just like any other variable */
someFunc(obj);


// illustration
(caller scope)        (someFunc scope)
           \             /
            \           /
             \         /
              \       /
               \     /
                 { }
                  |
                  |
                  |
            'Hello world'

Some final comments:

  • It's tempting to think that primitives are enforced by special rules while objects are not, but primitives are simply the end of the pointer chain.
  • As a final example, consider why a common attempt to clear an array doesn't work as expected.


var a = [1,2];
var b = a;

a = [];
console.log(b); // [1,2]
// doesn't work because `b` is still pointing at the original array

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"};
  alert("in changeObject: " + x.member);
}

function changeMember(x) {
  x.member = "bar";
  alert("in changeMember: " + x.member);
}

var x = {member:"foo"};

alert("before changeObject: " + x.member);
changeObject(x);
alert("after changeObject: " + x.member); /* change did not persist */

alert("before changeMember: " + x.member);
changeMember(x);
alert("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

Simple values inside functions will not change those values outside of the function (they are passed by value), whereas complex ones will (they are passed by reference).

function willNotChange(x) {

x = 1;

}

var x = 1000;

willNotChange(x);

document.write('After function call, x = ' + x + '<br>'); //still 1000

function willChange(y) {

y.num = 2;

}

var y = {num: 2000}; 

willChange(y);
document.write('After function call y.num = ' + y.num + '<br>'); //now 2, not 2000

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

sharing what I know of references in javascript

In Javascript, objects are stored as references:

var a = {
  a: 1,
  b: 2,
  c: 3
};
var b = a;

//b.c is referencing to a.c value
console.log(b.c) //output: 3
//changing value of b.c
b.c = 4
//also changes the value of a.c
console.log(a.c) //output: 4

Passing arguments to a function in JavaScript is analogous to passing parameters by pointer value in C:

/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.

function changeStuff(num, obj1, obj2)
{
    num = num * 10;
    obj1.item = "changed";
    obj2 = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);    
console.log(obj2.item);

This produces the output:

10
changed
unchanged
*/

#include <stdio.h>
#include <stdlib.h>

struct obj {
    char *item;
};

void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
    // make pointer point to a new memory location
    // holding the new integer value
    int *old_num = num;
    num = malloc(sizeof(int));
    *num = *old_num * 10;
    // make property of structure pointed to by pointer
    // point to the new value
    obj1->item = "changed";
    // make pointer point to a new memory location
    // holding the new structure value
    obj2 = malloc(sizeof(struct obj));
    obj2->item = "changed";
    free(num); // end of scope
    free(obj2); // end of scope
}

int num = 10;
struct obj obj1 = { "unchanged" };
struct obj obj2 = { "unchanged" };

int main()
{
    // pass pointers by value: the pointers
    // will be copied into the argument list
    // of the called function and the copied
    // pointers will point to the same values
    // as the original pointers
    changeStuff(&num, &obj1, &obj2);
    printf("%d\n", num);
    puts(obj1.item);
    puts(obj2.item);
    return 0;
}

Javascript is always pass-by-value, everything is of value type. Objects are values, 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";
alert(x.foo);
x.foo = 12;
alert(x.foo);

In both alerts you will find the value to be undefined.


Object outside a function is passed into a function by giving a reference to the outside obejct. When you use that reference to manipulate its object, the object outside is thus affected. However, if inside the function you decided to point the reference to something else, you did not affect the object outside at all, because all you did was re-direct the reference to something else.


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, JS 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


There's some discussion about the use of the term "pass by reference" in JS 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.)


It's interesting in Javascript. Consider this example:

function changeStuff(a, b, c)
{
  a = a * 10;
  b.item = "changed";
  c = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);
console.log(obj1.item);    
console.log(obj2.item);

This produces the output:

10
changed
unchanged
  • If it was pure pass by value, then changing obj1.item would have no effect on the obj1 outside of the function.
  • If it was pure pass by reference, then everything would have changed. num would be 100, and obj2.item would read "changed".

Instead, the situation is that the item passed in is passed by value. But the item that is passed by value is itself a reference. Technically, this is called call-by-sharing.

In practical terms, this means that if you change the parameter itself (as with num and obj2), that won't affect the item that was fed into the parameter. But if you change the INTERNALS of the parameter, that will propagate back up (as with obj1).


In some case, this may be helpful to alter anArg:

function alterMyArg(func) {
    // process some data
    // ...
    func(data);
}

alertMyArg(function(d) {anArg = d;});

I have found the extend method of the Underscore.js library very useful when I want to pass in an object as a parameter which may either be modified or replaced entirely.

function replaceOrModify(aObj) {
  if (modify) {

    aObj.setNewValue('foo');

  } else {

   var newObj = new MyObject();
   // _.extend(destination, *sources) 
   _.extend(newObj, aObj);
  }
}

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?


My 2 Cents.... This is the way I understand it. (Feel free to correct me if I'm wrong)

It's time to throw out everything you know about pass by value / reference.

Because in JavaScript, it doesn't matter whether it's passed by value or by reference or whatever. What matters is mutation vs assignment of the parameters passed into a function.

OK, let me do my best to explain what I mean. Let's say you have a few objects.

var object1 = {};
var object2 = {};

What we have done is "assignment"... We've assigned 2 separate empty objects to the variables "object1" and "object2".

Now, let's say that we like object1 better... So, we "assign" a new variable.

var favoriteObject = object1;

Next, for whatever reason, we decide that we like object 2 better. So, we simply do a little re-assignment.

favoriteObject = object2;

Nothing happened to object1 or to object2. We haven't changed any data at all. All we did was re-assign what our favorite object is. It is important to know that object2 and favoriteObject are both assigned to the same object. We can change that object via either of those variables.

object2.name = 'Fred';
console.log(favoriteObject.name) // logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // logs Joe 

OK, now let's look at primitives like strings for example

var string1 = 'Hello world';
var string2 = 'Goodbye world';

Again, we pick a favorite.

var favoriteString = string1;

Both our favoriteString and string1 variables are assigned to 'Hello world'. Now, what if we want to change our favoriteString??? What will happen???

favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'

Uh oh.... What has happened. We couldn't change string1 by changing favoriteString... Why?? because strings are immutable and we didn't mutate it. All we did was "RE ASSIGN" favoriteString to a new string. This essentially disconnected it from string1. In the previous example, when we renamed our object, we didn't assign anything. (Well, actually... we did, we assigned the name property to a new string.) Instead, we simply mutated the object which keeps the connections between the 2 variables and the underlying objects.

Now, on to functions and passing parameters.... When you call a function, and pass a parameter, what you are essentially doing is "assignment" to a new variable, and it works exactly the same as if you simply assigned using the equal (=) sign.

Take these examples.

var myString = 'hello';

// Assign to a new variable (just like when you pass to a function)
var param1 = myString; 
param1 = 'world'; // Re assignment

console.log(myString); // logs 'hello'
console.log(param1);   // logs 'world'

Now, the same thing, but with a function

function myFunc(param1) {
    param1 = 'world';

    console.log(param1);   // logs 'world'
}

var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString); 

console.log(myString); // logs 'hello'

OK, now lets give a few examples using objects instead... first, without the function.

var myObject = {
    firstName: 'Joe',
    lastName: 'Smith'
};

// Assign to a new variable (just like when you pass to a function)
var otherObj = myObject;

// Let's mutate our object
otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl

console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Sue'

// Now, let's reassign
otherObj = {
    firstName: 'Jack',
    lastName: 'Frost'
};

// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object no longer mutates the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';

Now, the same thing, but with a function call

function myFunc(otherObj) {

    // Let's mutate our object
    otherObj.firstName = 'Sue';
    console.log(otherObj.firstName); // Logs 'Sue'

    // Now let's re-assign
    otherObj = {
        firstName: 'Jack',
        lastName: 'Frost'
    };
    console.log(otherObj.firstName); // Logs 'Jack'

    // Again, otherObj and myObject are assigned to 2 very different objects
    // And mutating one object no longer mutates the other
}

var myObject = {
    firstName: 'Joe',
    lastName: 'Smith'
};

// Calls myFunc and assigns otherObj to myObject just like otherObj = myObject
myFunc(myObject);

console.log(myObject.firstName); // Logs 'Sue', just like before

OK, if you read through this entire post, perhaps you now have a better understanding of how function calls work in javascript. It doesn't matter whether something is passed by reference or by value... What matters is assignment vs mutation.

Every time you pass a variable to a function, you are "Assigning" to whatever the name of the parameter variable is, just like if you used the equal (=) sign.

Always remember that the equals sign (=) means assignment. Always remember that passing a parameter to a function also means assignment. They are the same and the 2 variables are connected in exactly the same way.

The only time that modifying a variable affects a different variable is when the underlying object is mutated.

There is no point in making a distinction between objects and primitives, because it works the same exact way as if you didn't have a function and just used the equal sign to assign to a new variable.

The only gotcha is when the name of the variable you pass into the function is the same as the name of the function parameter. When this happens, you have to treat the parameter inside the function as if it was a whole new variable private to the function (because it is)

function myFunc(myString) {
    // myString is private and does not affect the outer variable
    myString = 'hello';
}

var myString = 'test';
myString = myString; // Does nothing, myString is still 'test';

myFunc(myString);
console.log(myString); // logs 'test'

Primitives are passed by value and objects are passed by reference. This is quite different from other languages like C, VB or Delphi. I can't say how they handle objects and primitives exactly, but I know of VB and Delphi that it can (and should) be specified.

php does something similar since version 5: all objects are passed by reference, but all primitives may be passed by reference, if preceeded by an ampersand (&). Otherwise primitives are passed by value.

So in javascript, if I pass an object X into a function via a parameter, it will still be X. If you are changing data inside the function (or any other object, but that's not important) that new value is also available outside the function.


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


A very detailed explanation about copying, passing and comparing by value and by reference is in this chapter of "JavaScript: The Definitive Guide" book.

Before we leave the topic of manipulating objects and arrays by reference, we need to clear up a point of nomenclature. The phrase "pass by reference" can have several meanings. To some readers, the phrase refers to a function invocation technique that allows a function to assign new values to its arguments and to have those modified values visible outside the function. This is not the way the term is used in this book. Here, we mean simply that a reference to an object or array -- not the object itself -- is passed to a function. A function can use the reference to modify properties of the object or elements of the array. But if the function overwrites the reference with a reference to a new object or array, that modification is not visible outside of the function. Readers familiar with the other meaning of this term may prefer to say that objects and arrays are passed by value, but the value that is passed is actually a reference rather than the object itself.

One thing I still cannot figure out. Check code below. Any thoughts?

function A() {}
A.prototype.foo = function() {
    return 'initial value';
}


function B() {}
B.prototype.bar = A.prototype.foo;

console.log(A.prototype.foo()); //initial value
console.log(B.prototype.bar()); //initial value

A.prototype.foo = function() {
    return 'changed now';
}

console.log(A.prototype.foo()); //changed now
console.log(B.prototype.bar()); //Why still 'initial value'???

The most succinct explanation I found was in the AirBNB style guide:

  • Primitives: When you access a primitive type you work directly on its value

    • string
    • number
    • boolean
    • null
    • undefined

E.g.:

var foo = 1,
    bar = foo;

bar = 9;

console.log(foo, bar); // => 1, 9
  • Complex: When you access a complex type you work on a reference to its value

    • object
    • array
    • function

E.g.:

var foo = [1, 2],
    bar = foo;

bar[0] = 9;

console.log(foo[0], bar[0]); // => 9, 9

I.e. effectively primitive types are passed by value, and complex types are passed by reference.


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 JS(string, number, boolean, undefined, 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" }
  • JS engine assigns the object to the variable c, 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

The variable doesn't "hold" the object, it holds a reference. You can assign that reference to another variable, 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 JS supported passing by reference.


For programming language lawyers, I've went through the following sections of ECMAScript 5.1 (which is easier to read than the latest edition), and go as far as asking it on the ECMAScript mailing list.

TL;DR: Everythings're passed by value, but properties of Objects are references, and the definition of Object is creepily lacking in the standard.

Construction of Argument Lists

Section 11.2.4 "Argument Lists" says the following on producing a argument list consisting of only 1 argument:

The production ArgumentList : AssignmentExpression is evaluated as follows:

  1. Let ref be the result of evaluating AssignmentExpression.
  2. Let arg be GetValue(ref).
  3. Return a List whose sole item is arg.

The section also enumerate cases where argument list has 0 or >1 arguments.

Thus, everything's are passed by reference.

Access of Object Properties

Section 11.2.1 "Property Accessors"

The production MemberExpression : MemberExpression [ Expression ] is evaluated as follows:

  1. Let baseReference be the result of evaluating MemberExpression.
  2. Let baseValue be GetValue(baseReference).
  3. Let propertyNameReference be the result of evaluating Expression.
  4. Let propertyNameValue be GetValue(propertyNameReference).
  5. Call CheckObjectCoercible(baseValue).
  6. Let propertyNameString be ToString(propertyNameValue).
  7. If the syntactic production that is being evaluated is contained in strict mode code, let strict be true, else let strict be false.
  8. Return a value of type Reference whose base value is baseValue and whose referenced name is propertyNameString, and whose strict mode flag is strict.

Thus, properties of Objects are always available as reference.

On Reference

It is described in section 8.7 "The Reference Specification Type", that references are not real types in the language - they're only used to describe the behavior of the delete, the typeof, and the assignment operators.

Definition of "Object"

It is defined in 5.1 edition that "An Object is a collection of properties". Therefore, we can infer, that the value of the object is the collection, but as to what is the value of the collection is poorly defined in the spec, and requires a bit of effort to understand.


given the way python handles values and references to them, the only way you can reference an arbitrary instance attribute is by name:

class PassByReferenceIsh:
    def __init__(self):
        self.variable = 'Original'
        self.change('variable')
        print self.variable

    def change(self, var):
        self.__dict__[var] = 'Changed'

in real code you would, of course, add error checking on the dict lookup.





javascript pass-by-reference pass-by-value