Javascript, by value and by reference

In Javascript we use to make a distinction between assigning values to variables by value or by reference. The difference being when two variables appear to mirror changes applied to one or another (by reference), or not (by value).

Let's see some brief examples.

By Value

var a = 3;
var b = a;

We say that primitives like numbers are passed to variables by value because if I later change the value of a, the variable b is unaffected.

a = 5;
console.log(b); // still returns 3

By reference

Alternatively, we use to say that objects are passed to variables by reference.

var c = {'name':'Jon'};
var d = c;

If I modify the object contained in c, the content of the variable d is also affected.

c.name = 'Janet';
console.log(d.name); // returns "Janet"

However, I feel like there is a misconception here. The variable d does not refer to the variable c. In order to manipulate that object we need a reference to it, and we achieve that with the variables c and d.

Both refer to same object (that's it, {'name':'Jon'}). Variables are basically placeholders we use to store and access values during the execution of our programs.

Simply put, variables do not refer to other variables, but all refer to their content.

Mental model

Making a distinction between assigning values to variables by value or by reference is a way to think about what is actually happening under the hood. Being Javascript one of the very few truly object oriented language (everything in Javascript is an object with the exclusion of primitives like numbers, booleans, and strings), when we set the variable d to equal c, what it is NOT happening is that d refers to c.

What actually is happening is that both now refer to the same object we created earlier.

What we passed to d is the reference to that object.

In a very similar way with the line var b = a; we passed a reference to the primitive 3.

Primitives are immutable

In Javascript primitives are immutable. Objects (including Arrays and Functions which are objects as well) are mutable.

All types except objects define immutable values (values, which are incapable of being changed). For example and unlike to C, Strings are immutable. We refer to values of these types as “primitive values”. — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures

Consequently we can’t change a number, or a boolean, not even a string. What we can do is to create a new number, a new boolean (true or to false), and/or a new string. The original number, boolean, or string is unaffected.

var s = 'hello';
var t = s.toUpperCase();
console.log(t); // returns "HELLO"
console.log(s); // returns "hello"

So, it is all “by reference”?

On the other hand, we can manipulate objects (and that includes arrays and functions). In fact this is what we observe when we manipulate the content of an object equally assigned to different variables.

On the other hand, since we cannot mutate primitives, we might think that the underlying mechanism might differ.

var e = 'Hello there!'; // a string is a primitive, therefore immutable
var f = e;
e = 'Hi there!'; // creates a new string and assign e to it
console.log(f); // f still refers to the previous string

When I assign e to a new string, I’m not modifying the value of the previous string. I am creating a new one. Therefore when I assign e to a new primitive the variable f is not affected because now e refers to an entirely new string. It would be affected if I could mutate a string, which I can't.

On the other hand, we have the ability to change objects.

We can manipulate the content of an object so we might think that the variable d refers to the variable c, and c to the original object. But that's not correct in that both refer to the object, directly.

var c = {'name':'Jon'};
var d = c;
c = {'name':'Jon'}; // creates a new object
c.name = 'Janet'; // I can change objects
console.log(d.name); // returns “Jon”

When I repeated the line c = {'name':'Jon'} a second time, de facto I created a new object, that just looks identical to the previous one. Doing so now c and d point to different objects, therefore changing one does not affect the other any longer. That's not really different then assigning variables to different primitives.

var a = 3;
var b = a;
var a = 5;
console.log(b); // still returns 3

Conclusion

Ultimately it is a mere way of seeing it. I believe that the better I understand the code I write, the more elegant and reliable this will be.

For a further readings on Value vs Reference in Javascript I would recommend delving into the really brilliant essay written by Kyle Simpson: Value vs. Reference, part of his series of books You don't know Javascript.