JavaScript WordBook

Providing simple explanations for seemingly complex development terms

Handling data - value vs reference

In JavaScript the built-in data structures are either primitive or non-primitive. How data is handled, including how it is stored, accessed, changed and compared varies depending on if the data is a primitive value and the specific implementation. 

Understanding how data is handled is a valuable skill that will help you to create optimal, bug free solutions.

Let’s dive into the difference between how primitive and non-primitive data is handled with a couple of examples. 

Primitive values 

There are 7 primitive data types in JavaScript, which are: 

  1. String 
  2. Number 
  3. Biginit
  4. Boolean
  5. Null
  6. Undefined
  7. Symbol

Storing

Where data is stored depends on the implementation in the JavaScript engine interpreting the code but generally primitives are stored on the stack.

Accessing

Primitives are accessed directly by value, which means when referencing a variable assigned to a primitive you are directly referencing that data.

Updating 

Primitives are immutable, their value cannot be altered once set. 

This may seem confusing as you can update a variable that references a primitive value. However, what actually happens is the value that the variable references changes, the value itself is not changed.

// Javascript
let examplePrimitive = 'Example Primitive';

// Returns "Example Primitive", logs "example primitive"
examplePrimitive.toLowerCase();
console.log(examplePrimitive);

// Returns "example primitive", logs "example primitive"
examplePrimitive = examplePrimitive.toLowerCase();
console.log(examplePrimitive);

Comparing

Primitives are compared by value, for example:

// Javascript
const age = 30;
const daysInSeptember = 30;

// Returns true
console.log(age === daysInSeptember);

It doesn’t matter that the variables are not the same, all that matters is that the values assigned to them are. 

Non-primitive values (Object references)

Non-primitive data types are types of objects, which includes:

  1. Array
  2. Function
  3. Object

Storing 

As non-primitives are more complex data structures and can have properties and methods these are stored on the heap.

Accessing 

One of the notable differences between primitive and non-primitive data is what happens when we try to reference existing data. This is because non-primitive data is handled by reference.

In this example we have two sliders with options passed by object. We want both to have the same settings but with one altered property. Rather than creating the same object twice we’ve decided to simply copy the first object and change one of the values, sounds straightforward enough! 

// Javascript
const sliderOneOptions = {
   infinite: true,
   autoplay: true,
   slidesToScroll: 3,
   speed: 300,
};

const sliderTwoOptions = sliderOneOptions;

sliderTwoOptions.infinite = false;

console.log('Slider One options', sliderOneOptions);
console.log('Slider Two options', sliderTwoOptions);

If you run this code in your console you should see an output of:

// Javascript
// Slider One options
{
    infinite: false, 
    autoplay: true, 
    slidesToScroll: 3, 
    speed: 300
}

// Slider Two options
{
    infinite: false, 
    autoplay: true, 
    slidesToScroll: 3, 
    speed: 300
}

You may be surprised to see both objects are exactly the same, so what’s actually happened?

First we declare a variable called ‘sliderOneOptions’, which we assign an object with 4 properties on. Without a deeper understanding of how the JavaScript engine works it may appear that the object is stored in the variable, however what actually happens is the JavaScript engine establishes you’re assigning a non-primitive to a variable. The object is then assigned to a space in memory and a marker that references this point is assigned to the variable. 

We’ve then created a variable called ‘sliderTwoOptions’ and pointed that to ‘sliderOneOptions’. As this is just a reference to the location of the ‘sliderOneOptions’ object in memory this just adds a marker to ‘sliderTwoOptions’, which points to the same location in memory. 

As both variables are referencing the same object in memory. This means when we change a value on the object by referencing either variable it actually changes the same object.

Updating 

Non-primitives are mutable and can be altered after being assigned.

// Javascript
const sliderOneOptions = {
    infinite: false,
    autoplay: true,
 };

 sliderOneOptions.slidesToScroll = 4;

 // Logs { autoplay: true, infinite: false, slidesToScroll: 4 }
 console.log(sliderOneOptions);

Comparing

Non-primitives are compared by reference, you can see this in the following example: 

// Javascript
const sliderOneOptions = {
   infinite: false,
   autoplay: true,
   slidesToScroll: 3,
   speed: 300
};

const sliderTwoOptions = {
   infinite: false,
   autoplay: true,
   slidesToScroll: 3,
   speed: 300
};

const sliderThreeOptions = sliderOneOptions;

// Logs false
console.log(sliderOneOptions === sliderTwoOptions);

// Logs true
console.log(sliderOneOptions === sliderThreeOptions);

When comparing two objects that contain the exact same properties we see these don’t match, this is because we’re checking if it references the same object in memory, which it doesn’t. We can see further evidence of this when comparing the ‘sliderOneOptions’ and ‘sliderThreeOptions’  that both reference the same object.

Hopefully this article has provided you with a better grasp of how data is handled in JavaScript. Keep checking back as we’ll be regularly posting more definitions and diving into how different aspects of JavaScript work.