Demystifying JavaScript Equality: A Deep Dive into '==' and '==='

Sonal DiwanSonal Diwan
5 min read

Consider nice JavaScript example!

let s1 = 'Peter'
let s2 = 'Peter'
let s3 = new String('Peter');
let s4 = new String('Peter');
// Sample comparison code
if(s1 == s3){
    console.log("equal");
}else{
    console.log("not equal");
}

Let's break down what's happening in this code:

Variables and Assignments

We have four variables: s1, s2, s3, and s4. Each is assigned a value:

s1 and s2 are assigned the string literal 'Peter'. s3 and s4 are assigned a new instance of the String object, created using the new keyword, with the string literal 'Peter' as its value.

Comparison

The code then uses the (==) operator to compare s1 and s3. This is where things get interesting.

In JavaScript, when you use the == operator to compare two values, it performs a "loose equality" check.

  • Loose equality checks if the values of two operands are equal, without considering their data types. This means that JavaScript will perform type coercion, if necessary, to make the comparison.

String Literal vs. String Object

Here's the key point: s1 is a string literal, while s3 is a String object. Although they both represent the same string value, they are not the same type.

When you create a string literal, like 'Peter', JavaScript creates a primitive string value. On the other hand, when you create a String object using the new keyword, like new String('Peter'), JavaScript creates an object that wraps the string value.

Comparison Result

  • s1 == s3 Equal

  • s1 == s2 Equal

  • s1 == s4 Equal

  • s2 == s3 Equal

  • s2 == s4 Equal

  • s3 == s4 Unequal


  • s1 === s3 unequal

  • s1 === s4 unequal

  • s1 === s2 Equal

  • s2 === s3 unequal

  • s2 === s4 unequal

  • s3 === s4 unequal

- When the == operator compares s1 (a string literal) and s3 (a String object), it attempts to convert s3 to a primitive string value. This is done by calling the toString() method on the String object, which returns the underlying string value.

Since both s1 and the converted s3 value are now primitive strings, the comparison succeeds, and the code logs "equal" to the console.

Notes on '==='

  • If you were to use the ' \=== ' operator (strict equality) instead of ==, the comparison would fail, because s1 and s3 are not the same type.

  • Strict Equality (===)

    Strict equality, on the other hand, checks if the values of two operands are equal, while also considering their data types.

  • This means that JavaScript will not perform type coercion, and the operands must have the same data type and value to be considered equal.

String Pooling

In JavaScript, string literals are stored in a pool of strings, so that multiple references to the same string literal can share the same memory location. This is known as string pooling.

When you create a string literal, like 'Peter', JavaScript creates a primitive string value and stores it in the string pool. If you create another string literal with the same value, it will reference the same memory location in the string pool.

However, when you create a String object using the new keyword, like new String('Peter'), JavaScript creates a new object instance, which is not part of the string pool. This is why s3 and s4 are not considered equal, even though they have the same value.

Memory Allocation

In JavaScript, newly created objects, including String objects, are stored in the heap memory. The heap is a region of memory where objects are allocated and deallocated dynamically.

When you create a String object using the new keyword, JavaScript allocates memory for the object in the heap. The object's properties, including the wrapped string value, are stored in this allocated memory.

In contrast, primitive string values, like s1 and s2, are stored in the string pool, which is a separate region of memory.

Comparing a string object to a primitive string

The valueOf() method in JavaScript is used to return the primitive value of a specified object. It is a method that is available on all objects, including strings, numbers, booleans, and more.

In the context of your code, s3.valueOf() is used to return the primitive string value of the object s3. This is then compared to s1 using the strict equality operator (===).

Here's what's happening behind the scenes:

s3.valueOf() is called, which returns the primitive string value of s3. The returned value is then compared to s1 using the strict equality operator (===). If the two values are equal, the code logs "equal" to the console. Otherwise, it logs "not equal".

The valueOf() method is useful when you need to compare the primitive value of an object to another value. This is particularly useful when working with objects that have a primitive value, such as strings, numbers, or booleans.

Here are some examples to illustrate the concept:

const s1 = "hello";
const s2 = new String("hello"); // creates a String object
const s3 = new String("hello"); // creates another String object

console.log(s1 === s2); // false, because s1 is a primitive string and s2 is a String object
console.log(s1 === s2.valueOf()); // true, because s2.valueOf() returns the primitive string value
console.log(s2 === s3); // false, because s2 and s3 are different objects
console.log(s2.valueOf() === s3.valueOf()); // true, because both return the same primitive string value

In summary, the valueOf() method is used to return the primitive value of an object, which can be useful when comparing values using the strict equality operator (===).

Try your hands to code on the concept. and If you know of any more ways to compare, please share them in the comments !

1
Subscribe to my newsletter

Read articles from Sonal Diwan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sonal Diwan
Sonal Diwan

Data-Driven Fresher | Leveraging full stack technologies | Exploring tech-trends