What are the Differences Between Primitives and Objects in JavaScript?

Following are the differences between primitives and objects in JavaScript:

  1. Composition;
  2. Immutability;
  3. Pass by Value vs. Pass by Reference;
  4. Compare by Value vs. Compare by Reference;
  5. Copy by Value vs. Copy by Reference.

Composition

Primitives are not composed of any other data types, whereas objects may be composed of other objects. In fact, nearly all objects in JavaScript are a subclass of the Object class.

Immutability

Primitive values are immutable (i.e. they cannot be changed). In contrast to this, objects are not immutable by default.

For example, if you use a string method on a primitive string data type, it does not mutate the original string:

let foo = 'bar';
console.log(foo); // 'bar'

foo.toUpperCase();
console.log(bar); // 'bar'

You may reassign a variable to a new value, however, that still does not mutate the original string value, it merely reassigns the variable to a new value:

let foo = 'bar';
foo = foo.toUpperCase();
console.log(foo); // 'BAR'

In contrast to this, consider an object for example, where the original object properties can be mutated:

const obj = { name: 'John', age: 24 };
console.log(obj); // {name: 'John', age: 24}

obj.name = 'Jane';
console.log(obj); // {name: 'Jane', age: 24}

Pass by Value vs. Pass by Reference

When you pass a primitive as an argument to a function, it is passed by value (i.e. a copy of the primitive itself is passed). However, when you pass an object to a function, it is passed by reference. This means that the function would have a reference to the same object, and any modifications you make would actually be reflected in the original object. For example:

const person = { name: 'John', age: 24 };

function incrementAge(person) {
    person.age += 1;
    return person;
}

console.log(person.age); // 24

incrementAge(person);

console.log(person.age); // 25

In contrast, a primitive, such as a number for example, is passed by value:

const age = 24;

function incrementAge(age) {
    age += 1;
    return age;
}

console.log(age); // 24

incrementAge(age);

console.log(age); // 24

Compare by Value vs. Compare by Reference

Primitives are compared by value, whereas objects are compared by reference. This means that, while an object will always equal itself, two objects with same properties (even a deep or shallow copy of the object) won't be equal:

const obj1 = { color: 'blue' };
const obj2 = { color: 'blue' };
const obj3 = { ...obj1 };

console.log(obj1 === obj2); // false
console.log(obj3 === obj1); // false

In contrast to this, a primitive is always equal to the same primitive value. For example:

const color1 = 'blue';
const color2 = 'blue';

console.log(color1 === color2); // true

Copy by Value vs. Copy by Reference

A JavaScript variable can hold one of two value types; primitive values or reference values. When you assign a variable that stores a primitive value to another, the value stored in the variable is created and copied into the new variable. In case of an object, however, the new variable merely copies the reference to the original object.

In the following example, you can see how a primitive value is copied by value (and not by reference):

let color1 = 'blue';
let color2 = color1;

color1 = 'pink';

console.log(color2); // 'blue'
console.log(color1); // 'pink'

If the value was being copied by reference, both color1 and color2 would have the same value, even after the variable color1 was assigned to a new value.

In contrast to this, objects are copied by reference. This means that whenever you copy an object into a new variable, it would still have the reference to the original object. This is the reason why, when you modify the object using either variable, you would actually be modifying the original object:

const obj1 = { color: 'blue' };
const obj2 = obj1;

obj1.color = 'pink';
obj2.color = 'green';

console.log(obj1); // {color: 'green'}
console.log(obj2); // {color: 'green'}

console.log(obj1 === obj2); // true

This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.