Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any rules of thumb for when JavaScript values are copied by reference and not by value?

Tags:

javascript

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.

like image 443
buley Avatar asked Jan 30 '12 18:01

buley


People also ask

Is JavaScript copy by reference or value?

JavaScript is always pass-by-value. This means everything in JavaScript is a value type and function arguments are always passed by value.

Does JavaScript always pass parameters by value or by reference?

Therefore, even changing the argument inside the function doesn't affect the variable passed from outside the function. It is important to note that in javascript, all function arguments are always passed by value. That is, JavaScript copies the values of the passing variables into arguments inside of the function.

Is JavaScript is reference based or value based?

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.

Are variables passed by reference in JavaScript?

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.


2 Answers

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.

like image 181
josh3736 Avatar answered Oct 05 '22 23:10

josh3736


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.

like image 34
Šime Vidas Avatar answered Oct 06 '22 00:10

Šime Vidas