Javascript pass primitive by reference

You can't pass primitives by reference in Javascript - and the example "workaround" does not work. Here's why:

var foo = new Number(2)  // line 1
function inc (arg) {     // line 2
    arg++                // line 3
}

Line 1 sets foo to a Number object wrapper with primitive value 2.

Line 2 defines a formal parameter arg which has its own storage location in function scope to hold a copy of the value of the argument.

Line 3 increments the actual parameter value (a copy of the Number object reference) where it is stored - in memmory allocated for arg, not foo. If you check the primitive value of foo after the call it is still 2.

In practice you can pass a reference to an object with a foo property that is incremented:

var obj = {}
obj.foo = 2
function incFoo (obj) {
    obj.foo++
}
incFoo()  // obj.foo now 3

Essentially there are no address pointers available in ECMA script to reference primitive values.

Understanding how primitive data types and objects behave in JavaScript

Javascript pass primitive by reference

Photo by Glenn Carstens-Peters on Upsplash

If you are new to JavaScript, chances are you’ve already run into some of the funny behavior this language has to offer (exhibit A). At first, these weird quirks might seem ridiculous and frustrating, but I promise there is a method behind all of that madness.

One of the hardest hurdles to overcome, in my humble opinion, is the difference between passing by value vs passing by reference. Why is this concept so tricky? For starters, you can certainly get pretty far without really understanding how JavaScript interacts with primitive values and reference values. This can, and more often than not, will result in a ton of bugs that are hard to track down and annoying to fix. Secondly, this is a concept that WILL come up in technical interviews, so not understanding it will count as a huge red flag against you.

Fear not, fellow reader! Let the education begin…

Primitive Data Types

In JavaScript, we can divide data types into two different buckets, primitive data types and objects.

Javascript pass primitive by reference

Chart illustrating the primitive data types, or values, and the object types, or reference values

There are six primitive data types in JavaScript: string, number, boolean, undefined, null, and symbol as of ES6.

Primitive data types are passed, or copied, by value and are immutable, meaning that the existing value cannot be altered the way an array or an object can. Let’s take a look at the code below to see this in action.

Javascript pass primitive by reference

Created using jsbin.com

Here we have created two variables, x = 10 and y = x. Since 10 is a number and a primitive value, when we set y = x we are actually copying the value, i.e. 10, and assigning it to y. We can also visualize this using the chart below.

Javascript pass primitive by reference

If we were to change the value of x, we would see that y retains its value of 10. Again, this is because primitive values are copied, so y's value is independent of x's value. Think of it as making a photocopy of a picture. After making the copy, you have two identical pictures: an original and a facsimile. If you were to cut the original in half, only the original would be altered and the facsimile would remain exactly the same.

Javascript pass primitive by reference

Javascript pass primitive by reference

We overwrote the value of x but y remains the same

Reference Objects

Objects, on the other hand, are passed by reference and point to a location in memory for the value, not the value itself. Let’s take a look at this in our code.

Javascript pass primitive by reference

Variables x and y now point to objects rather than primitive data types

In this example, x is now an object pointing to {dog: "poodle"}. When we create the variable y and assign it the value of x, we are now able to tap into the various properties of x which includes the value for dog, i.e. "poodle". This seems like the exact same logic used for primitive values, but let’s take a look at our handy-dandy chart below to see the subtle, but important difference.

Javascript pass primitive by reference

Both x and y point to a (made up) address in memory which stores a reference to the object

Now this chart looks a little bit different from when our variables x and y held primitive data types. In this version, we see that the values for both x and y are not data types but references to an addresses in memory, the same address in fact! Now let’s take a look at what happens to x if we add a new property of size to y

Javascript pass primitive by reference

x still returns an object but now it has an additional property of size also! Again, this is because both x and y point to the same reference object, so any changes made to one variable, will be visible in the other.

Javascript pass primitive by reference

Chart illustrates how a change in y updates the reference value that is shared with x

To help me remember this concept, I like to think of reference values as a house and the variables as people who live in that house. All of the residents (variables) can say “I have a house” and point to the same house. If a single resident decides they want to paint the house yellow, then all the residents now have a yellow house because it is shared.

Let’s take a look at one more example that contain a variety of reference objects.

Javascript pass primitive by reference

In this code, we start out with a variable person that contains properties of name, age, and hobbies. When we print this object to the console, we get exactly what we expect — the same object we just created.

Next, we have a function called changePerson that takes in an argument, makes a few changes, then returns an object. When we create the variable thirdPerson, we invoke thechangePerson function by passing our original object of person into it. The interesting bit is what happens when we print to the console thirdPerson and person again.

Notice that console.log(thirdPerson) returns a whole new object with new properties. Now look at what console.log(person) returns. This is similar to our original object but it contains new property values that were introduced in our changePerson function.

Checking for Equality

Finally, let’s take a look at how primitive data types and reference objects behave with equality operators.

Javascript pass primitive by reference

When it comes to primitive data types, it doesn’t matter what is to the right of the = sign as long as the values are the same. We can see this above with variables a and b which are written differently but evaluate to the same value when we use the ===, the strict equality operator.

The opposite is true in the second example for dog and cat. While it may appear that they contain identical values, ['bark'] is an array, and a reference object, which means the === is checking to see if both dog and cat have the same reference to the value in memory. On the other hand, bird === dog is true because they share the same reference object.

Javascript pass primitive by reference

dog and bird share the same reference while cat does not despite having an identical array

Conclusion

And that concludes our introduction into pass by value vs pass by reference. There are more topics that can be covered under this umbrella fundamental, including what happens when a reference is overwritten or lost, how to copy a reference to create a new object AND make sure that the copy is a deep copy, just to name a few. I would recommend checking out the resources I used below which do go into some of these additional topics in greater detail.

Thank you for reading! I myself am relatively new to coding so if you have any comments, corrections, hostilities, and/or desires, please leave a comment below!

Resources

Below are just a handful of amazing resources out there to help you understand passing values vs passing references in JavaScript.

How do you pass a primitive type by reference in JavaScript?

There is no pass-by-reference in JavaScript for primitives. In other OO languages, we can pass "pointers" or "references" to functions not nearly all of them. Java, for example, doesn't even have functions (not real ones, anyway - Java 8 has syntactic sugar over classes).

Can JavaScript pass by reference?

In Pass by Reference, a function is called by directly passing the reference/address of the variable as the argument. Changing the argument inside the function affects the variable passed from outside the function. In Javascript objects and arrays are passed by reference.

Does JavaScript pass by value or by reference?

JavaScript is always pass-by-value. This means everything in JavaScript is a value type and function arguments are always passed by value. That being said, object types are a bit more confusing. The confusion lies in the fact that object types are reference types which are passed by value.

Are primitives passed by value in JavaScript?

Primitive data types such as string, number, null, undefined, boolean, are passed by value while non-primitive data types such as objects, arrays, and functions are passed by reference in Javascript.