Short Circuiting in JavaScript

Introduction

Consider the following code snippet:

// if-else statement
if (isUserLoggedIn) {
    return privateData;
}
else {
    return false;
}

The above code can be written in a more concise way like this:

// Short Circuiting
isUserLoggedIn && privateData;

This is an example of short-circuiting and it makes our code more concise.

Short-Circuiting: How the evaluation is done by JavaScript?

We use the && and || operators to achieve short-circuiting in JavaScript.

When these operators are used, the expression on the left-hand side is evaluated first. If the result of the left-hand side expression is sufficient to determine the overall result of the operation, the right-hand side expression is not evaluated.

💡 Short-circuiting expressions are evaluated from left to right

Short-Circuiting using the && operator

A short-circuiting expression using the && operator will return either the first falsy operand or the last operand.

const countryName = "India"; // truthy
const countryPopulation = "1.4 Billion" // truthy
const countryRanking = 106; // truthy
const countryWorldCupAppearances = 0; // falsy
const countryWorldCupTitles = ""; // falsy

// AND (&&) operator with no falsy operands (returns the last operand)
console.log(countryName && countryPopulation && countryRanking);
// Output: 106

// AND (&&) operator with truthy and falsy operands (returns the first falsy operand)
console.log(countryRanking && countryWorldCupTitles && countryName); 
// Output: ""

Short-Circuiting using the || operator

A short-circuiting expression using || operator will return either the first truthy operand or the last operand.

const countryName = "India"; // truthy
const countryPopulation = "1.4 Billion" // truthy
const countryRanking = 106; // truthy
const countryWorldCupAppearances = 0; // falsy
const countryWorldCupTitles = ""; // falsy

// OR (||) operator with no truthy operands (returns the last operand)
console.log(countryWorldCupTitles || countryWorldCupAppearances);
// Output: 0

// OR (||) operator with truthy and falsy operands (returns the first truthy operand)
console.log(countryWorldCupTitles || countryName || countryPopulation);
// Output: "India"

A problem with short-circuiting using the || operator

Consider the following code snippet:

const setQuantityPerPacket = (item, quantity) => item.qty = quantity || 7;

Here we have used short-circuiting with the || operator to set a default value for item.qty in case the quantity parameter isn’t passed to setQuantityPerPacket function.

Let’s see this with an example:

// When item and qty is passed to the setQuantityPerPacket function
const apple = {
    itemType: "fruit",
    pricePerKg: 130,
}

setQuantityPerPacket(apple, 4);
console.log(apple.qty);
// Output: 4

// When only item and no quantity value is passed to the setQuantityPerPacket function
const orange = {
    itemType: "fruit",
    pricePerKg: 60,
}

setQuantityPerPacket(orange); // no quantity value passed as second argument
console.log(orange.qty);
// Output: 7
// i.e, the default value we gave using short circuiting

So in the above example, everything is working fine.

So then what is the problem?

The problem arises when we want to specify 0 as the number of items per packet (0 as the quantity per packet seems weird, right? 🙃)

const brinjal = {
    itemType: "vegetable",
    pricePerKg: 40,
}

setQuantityPerPacket(brinjal, 0);
console.log(brinjal.qty);
// Output: 7 
// We wanted 0 to be the output, but who invited 7 here?!

So how did this happen?

Why is 7 the output? We wanted 7 to be item.qty only if the second argument is not passed to the function. But here we have passed 0 as the second argument, right?

Why is 0 not the output?

And the answer to all these questions is that 0 is a falsy value just like undefined and so the || operator moved on to the next operand in search of a truthy value instead of short-circuiting.

Let’s look at the definition of setQuantityPerPacket function again:

const setQuantityPerPacket = (item, quantity) => item.qty = quantity || 7;

So if we pass 0 as the second argument to the function, it will return the result of the following expression:

0 || 7
// OR operator will short circuit as soon as it sees a truthy value
// But 0 isn't truthy and so it moved on to 7 and returns it

But we just wanted the default value to be used if the quantity is undefined , right?

But unfortunately the || operator can’t differentiate between undefined and 0.

So what’s the solution to this problem?

The solution: Nullish Coalescing Operator ( ?? )

I was overwhelmed when I first saw this name - Don't be like me 🙆

Nullish Coalescing Operator is just another logical operator like the AND and OR operators.

💡 When used in a short-circuiting expression, the ?? operator returns the first non-nullish operand or the last operand.

So what are nullish values?

Just like we have truthy and falsy values, we have nullish values in JavaScript.

The nullish values in JavaScript are null and undefined. Every other value is a non-nullish value in JavaScript.

Falsy ValuesNullish ValuesTruthy Values
false, "" (empty string), null, undefined, NaNnull, undefinedAll values that are not falsy

So though the || operator couldn't distinguish between undefined and 0, we now have the ?? operator that could.

So let's use it to rewrite setQuantityPerPacket function to solve the problem we faced before:

const setQuantityPerPacket = (item, quantity) => item.qty = quantity ?? 7;

So now if we pass the quantity value as 0, it will indeed be set to 0 and not 7.

setQuantityPerPacket (brinjal, 0);
console.log(brinjal.qty)
// Output: 0

Conclusion

Short-circuiting is an awesome technique in JavaScript that will help us write concise and expressive code that avoids unnecessary computations. It is a valuable tool for developers to have in their toolkits.