JavaScript is an Object-Oriented language: this means that most things in JavaScript are Objects. For example, functions are Objects. The only elements that are not objects are the Primitive Data Types : string, number, boolean, null and undefined. These Primitive Data Types also are immutable, which means that once created they cannot be modified.
One of the differences between the two is that Primitive Data Types are passed By Value and Objects are passed By Reference.
Primitive Data Types are passed By Value and Objects are passed By Reference.
What does this mean ? You can think of it this way:
Let’s examine how Primitives and Objects behave, first when we assign them values with the assignment operator (=), and second when we pass them to a function as a parameter.
Consider the following code:
var name = "Carlos";var firstName = name;name = "Carla";
console.log(name); // "Carla"console.log(firstName); // "Carlos"
The result is pretty straightforward : that’s the = operator working by value. What really happens here can be simplified as follows :
name
is created and given the value of "Carlos". JavaScript allocates a memory spot for it.firstName
is created and is given a copy of name
's value. firstName
has its own memory spot and is independent of name
. At this moment in the code, firstName
also has a value of "Carlos".name
to "Carla". But firstName
still holds its original value, because it lives in a different memory spot.When working with primitives, the =operator creates a copy of the original variable. That’s what by value means.
Consider the following code :
var myName = {firstName: "Carlos"};var identity = myName;myName.firstName = "Carla";
console.log(myName.firstName); // "Carla"console.log(identity.firstName); // "Carla"
Here the output is the same for the variables containing objects. That happens because, when dealing with objects, the =operator works by reference. What is really happening can be described as follows:
myName
is created and is given the value of an object which has a property called firstName
. firstName
has the value of "Carlos". JavaScript allocates a memory spot for myName
and the object it contains.identity
is created and is pointed to myName
. There is no dedicated memory space to _identity_
's value'. It only points to myName
's value.myName
's firstName
property to "Carla" instead of "Carlos".When we log myName.firstName
it displays the new value, which is pretty straightforward. But when we log identity.firstName
its also displays myName.firstName
's new value "Carla". This happens because identity.firstName
only points to myName.firstName
’s place in the memory.
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.
If you change the value of a Primitive Data Type inside a function, this change won’t affect the variable in the outer scope:
var myName = "Carlos";function myNameIs(aName){aName = "Carla";}myNameIs(myName);
console.log(myName); // "Carlos"
Even if we are changing the myName
variable inside of the function myNameIs
, when we print it after calling the function, it still has the value "Carlos". That is because when primitive types are passed, they are passed by value.
We are passing a copy of myName
: anything you do to myName
inside the body of the function won't affect the myName
variable in the global scope because you are passing a copy of myName
, and not the original myName
variable.
When you are passing something by reference, you are passing something that points to something else, not a copy of the object. So since JavaScript passes objects by reference, when you change a property of that object within the function, the change will be reflected in the outer scope:
var myName = {};function myNameIs(aName){aName.firstName = "Carla";}myNameIs(myName);
console.log(myName); // Object {firstName: "Carla"}
Now if I log the myName
variable after having invoked the function myNameIs
, it logs an object with a key of firstName
with a value equal to "Carla". The object did change in the global scope when we passed it to the function.
This is because when you pass an object into the function, you are not passing a copy. You are passing something that points to the myName
object. So when you change a property of that object in the function, you are changing the property of the object in the outer scope.
But there is a subtlety you should be aware of:
var myName = {firstName: "Carla"};
function myNameIs(aName){aName = {nickName: "Carlita"};}
myNameIs(myName);console.log(myName); // Object {firstName: "Carla"}
Here it prints the value of the variable myName
in the outer scope and didn't add a nickName
property to the object this time. Why is that ? If you look carefully, what we are doing in the function is trying to reassign the myName
object a new value.
But you can’t change what myName
points to, you can only change a property of myName
to something else, like this:
var myName = {firstName: "Carla"};
function myNameIs(aName){aName.nickName = "Carlita";}
myNameIs(myName);console.log(myName); // Object {firstName: "Carla", nickName: "Carlita"}
Want to learn more ? Check out my other articles on the basics of JavaScript:
I hope you enjoyed this explanation of “By Value” and “By Reference”.
Feel free to comment and like this article so that others can find it easily on Medium !