6

Even as a somewhat seasoned JS dev I find myself constantly suprised at shallow vs. deep copies of objects.

Are there any rules of thumb for when JavaScript values are copied by reference and not by value for the major object types? For example, I know string values are always copied by value not reference.

buley
  • 28,032
  • 17
  • 85
  • 106
  • Depends on your method of copying. You have to be specific - how do you copy your values? – Šime Vidas Jan 30 '12 at 19:11
  • Or did you mean the case when a value is passed as an argument into a function? – Šime Vidas Jan 30 '12 at 19:27
  • Rather than passed via arguments I am thinking of a simple `var x, y; x = { 'blah': 'foo' }; y = x; x = { 'bar': 'bas' }; console.log( y );` kind of situations, but if there's more nuance to the types of copying than please let me know how I can improve the question. – buley Jan 30 '12 at 19:46
  • 2
    Pedant hat: JavaScript is *strictly* pass-by-value. – Wayne Jan 30 '12 at 20:21
  • 3
    @lwburk Well, but it's confusing when you don't realize how many *values* in JavaScript are themselves references. – kojiro Jan 30 '12 at 20:30

2 Answers2

4

In JavaScript, all objects are stored and passed 'by reference'.

var a = { v: 'a' }, b = { v: 'b' };
a=b;
b.v='c';

a and b will reference the same object; a.v == 'c' and b.v == 'c'.

Primitive datatypes (string, number, boolean, null, and undefined) are immutable; they are passed by value.

var a = 'a', b = 'b';
a=b;
b='c';

Since we're dealing with primitives, a == 'b' and b == 'c'.


Pedants will tell you that JavaScript isn't pass-by-reference in a classical sense, or that it's a "pure pass-by-value" language, but I think that complicates things for practical purposes. No, you can't directly modify an argument passed to a function as if it were a variable (which would be true if the language were true pass-by-reference), but you also don't receive a copy of an object passed as an argument (as you would if it were true pass-by-value). For most purposes (from the standpoint of the language's user, you), objects passed to a function are references, since you can modify that object and it affects the caller's object. See also the fantastic answers to this question.

Community
  • 1
  • 1
josh3736
  • 139,160
  • 33
  • 216
  • 263
2

OK, let me explain your code:

var x, y;
x = { 'blah': 'foo' };
y = x;
x = { 'bar': 'bas' };

So, you declare two variables, and then you assign an object value to the first variable:

x = { 'blah': 'foo' };

So, what happens here:

  1. The object literal - { ... } - is evaluated, which results in the creation and initialization of a new native object.
  2. A reference to this object is assigned to the variable x.

Next, this line

y = x;

merely copies the reference which is stored in x to the variable y. Now both variables store the same reference to the object.

Finally, this line

x = { 'bar': 'bas' };

assigns a new value to the variable x. The object literal is evaluated which results in the creation/initialization of another object, and a reference to that object is stored in x.

The variable y, however, still holds a reference to the first object.

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385