The basics of JS: by value and by reference
Anyone with the slightest notion of programming or mathematics can pretty much deduce what the following line of code means:
var a = 5;
It means the variable a holds the value of 5. Right? We can confirm that by typing it in our browser console.
There are two fundamental rules we have to keep in mind when dealing with the = operator in JS.
1 — With primitive types, = operator works by value
First of all, what are primitive types? In JS those types are: boolean, null, undefined, number, string and symbol (the latter with ECMAScript 6).
Now let’s take a look at the following code.
What will the console display?
Pretty straightforward, right? That’s the = operator working by value.
What really happens is the following (in reality, this process is a simplified version of what happens, but it is enough for this article. If you want to really understand what happens under the hood, read this):
1 — On line 1, a variable foo is created and is given the value of “bar”. JS allocates a memory spot for it.
2 — On line 2, a variable baz is created and is given a copy of foo’s value. baz has its own memory spot and is independent of foo. At this moment, baz ALSO has a value of “bar”.
3 — On line 4, we changed the value of foo, which is now ban. But baz still holds its original value, because it lives in a different memory spot.
That is shown at the console, as expected.
2 — With objects, = operator works by reference
With the previous example in mind, what should we expect when using objects instead of primitive values? What should the following code output?
That’s where many newbies to the language get confused. I’ve lost my share of hair trying to figure out what was up. Contrary to what we might expect, the output is the following:
That happens because, when dealing with objects, the = operator works by reference.
What happens can be easily described as this:
1 — On line 1, a variable foo is created and is given the value of an object which has a property called “output”. Output has the value of bar. JS allocates a memory spot for foo and its object.
2 — On line 4, a variable baz is created and is POINTED to foo. There’s no memory space to baz’s value. It only points to foo’s value.
3 — On line 6, we changed the value of foo’s ‘output’ property, to “bar”.
When we log foo.output it displays its value. When we log baz.output it ALSO displays foo.output’s value, because it only points to that place in the memory.
Thus, when working with objects, the = operator creates an alias to the original object. It doesn’t create a new object. That’s what by reference means.
When we use = with primitive values, it creates a COPY of the original value. It’s like twins. They are born equal, but Twin Foo doesn’t lose his arm when Twin Baz loses his in a tragic accident. That’s called by value.
When we use = with objects, it creates an alias to the original object. When you’re born you are given a name. When you get friends and they give you a nickname (because you are so cool) you don’t suddenly give birth to a copy of you. You’re still one, but can be called by two different things.