Wizardry behind JavaScript variable types

Before we take a deep dive into the concept of immutability, let’s go back to the roots and clear out few things about types in JavaScript.

As you have probably read in countless tutorials and books, those are divided into two species:

Primitive types, e.g. number, string, boolean

Reference types, e.g. objects, arrays, functions

(As a matter of fact, arrays and functions are also objects — but let’s put this quirk aside for now, JavaScript was never a normal fellow anyway.)

The question that does matter right now is: what’s the difference between two mentioned types of variables? Let’s make it clear, step by step.

For starters, let’s have some variables with assigned values. For example:

Since the universe is a pretty dynamic concept — and so does programming — usually our goal is to have those values changed into something else. Preferably, we will have a function that does it for us:

Now, let’s begin with a string variable and try to write a function that will transform it. We will begin with dumb and naive approach first: (Warning, idiotic and obviously ineffective code ahead!)

Obviously, this piece of code doesn’t look like a brilliant one (frankly, it’s idiotic). This function tries to change the value of the parameter variable to something else — but upon calling, logging out the variable to the console still ends up in displaying original value.

Can it work properly? Silly, of course not. As you obviously know, the body of our function have received a copy of variable someString in its argument, so any changes will be made only to the duplicated string — the original one will stay untouched. If we really want to achieve our goal, we need to return a value from our function. Something like this:

This one works as intended — our function managed to process and return the data, despite having a copy of our function. But what does the concept of copy mean in JavaScript?

Now, let’s try to do the same with the object. And similarly like we did with the string, we will start with naive approach. Behold, the supposedly moronic code:

Ok, let’s run. Uh-oh. Did it work?

Bummer. It worked — but things that unexpectedly work in a miraculous way are rarely a good sign.

Let’s analyse it: if we were to follow the same logic as in the case with string , we would expect that the object will be copied. Then, all our changes will be performed on the copy, not the original. Instead, we somehow managed to modify the object in-place. Why is it happening?

The truth is that our function did copy the argument — but both variable names ( someObject and input ) are referring to the same object. To be exact, both hold the same reference — they relate to the same place in the computer’s memory. We can mimic this behaviour even through simple assignments:

Similarly, both variables here are holding the reference to the very same object. And when using " = " operator, we don’t copy the object — we merely assign an address to the place in the memory. If you want to feel more confident while working with object assignments, you can always look up how many times the object was created.

This is a creation of a new object:

This is not:

Modern humanity knows only three methods of creating objects in JavaScript:

immediate creation using curly braces { and } (just as in example above)

and (just as in example above) using Object.create()

using new operator

Any other operation: assignment, passing as a parameter, returning something from a function — will not end up in creating a new object (at least in conventional JavaScript).

Keep in mind that we’re talking about the objects in this article, but basically all of those principles apply to arrays as well. After all, they’re also objects.

Okay, so where is it going? Apparently, there is another side of the story with assigning references of same objects — and it’s pretty nasty.