Learn Why && and || Returns No-Booleans in JavaScript

Every day, software developers working with JavaScript learn something new about the programming language. Its flexibility makes it easy to use for new programmers, but there are many concepts that are not as straightforward such as understanding why logical operators like AND (&&) and OR (||) don’t always return boolean values.

Not What You Think

For instance, any developer with a background in C# or Java, even JavaScript developers themselves, will quickly assume the value of isCarMustang variable to be a boolean in the following code snippet.

const car = { brand: 'Ford', model: 'Mustang' };
const isCarMustang = car && car.model;

if (isCarMustang) {
   console.log('horse');
}

In theory, this code will log ‘horse’ correctly, but the reason is not because isCarMustang is a boolean, which it is not, but it is a truthy value instead.

Understanding ECMA Specifications

According to ECMA specifications section 13.13, the value produced by a && or || operator is not necessarily of type Boolean. The value produced will always be the value of one of the two operand expressions. For many, the second part of the concept is still not clear besides knowing now booleans values will not always be returned as per ECMA specifications.

The reason why the second part of the ECMA specification The value produced will always be the value of one of the two operand expressions might not make sense is because of the last two words operand expressions.

What are Expressions and Operands?

Let’s break it down into smaller pieces to understand what expressions and operands are.

In JavaScript, an expression performs actions that generate a value using operators and operands. For instance, the following snippet of code is an expression:

2 + 1

Where

  • the operator is +
  • 2 and 1 are operands

Having that as a reference, we can start getting an idea of what an operand is.

An operand is a piece of data or an entity in JavaScript, and it can be in any data type. This means operands can be strings, booleans, numbers, objects, arrays, etc.

Understanding Truthy and Falsy Values

Learning what truthy and falsy mean will help us clarify doubts with regards to the functionality of how AND and OR logical operators work in JavaScript as you can use any kind of operand when using logical operators, regardless if one operand is a number, another is a string, another an array, etc.

A falsy value in JavaScript is a false value as the result of converting the original value to a boolean. For instance, if the original value is null, attempting to convert null into boolean results in a false value.

In JavaScript, false, 0, -0, 0n, "" or an empty string, null, undefined, NaN are considered falsy values as attempting to convert them to booleans results in false.

Boolean(false);     // false
Boolean(0);         // false
Boolean(-0);        // false
Boolean(0n);        // false
Boolean("");        // false
Boolean('');        // false
Boolean(``);        // false
Boolean(null);      // false
Boolean(undefined); // false
Boolean(NaN);       // false

A truthy value in JavaScript is a true value as the result of converting the original value to a boolean. For instance, if the original value is "Mustang", attempting to convert "Mustang" into boolean results in a true value.

In JavaScript, all values are truthy except for the values defined as falsy (false, 0, -0, 0n, "" or an empty string, null, undefined, NaN).

Boolean(true);             // true
Boolean(0.1);              // true
Boolean(-5);               // true
Boolean('Foo');            // true
Boolean("Bar");            // true
Boolean({ a: 'anything' });// true
Boolean({});               // true
Boolean([1,2,3,4,5]);      // true
Boolean([]);               // true
Boolean(new Date());       // true
Boolean(Infinity);         // true

How AND (&&) Operator Works

The logical operator AND (&&) returns either the value of the first falsy operand it finds or the value of the last operand if all values are truthy.

The way the logical operator AND applies its logic is by reading the operand values from left to right. Hence, in the following snippet of code, the AND operator will start determining first whether operand1 is truthy or falsy. If it is truthy go to the next operand, which is operand2, and determine whether it is truthy or false. This process continues until it finds the first falsy value or reaches the last operand.

operand1 && operand2 && operand3

Given the following example where 1 and 2 are truthy values, the value of the last operand will be returned.

1 && 2     // 2 is returned

However, if we use 0 and 1 with the AND operator, it will find at determine at some point that 0 is a falsy value, which according to how the AND operator works, will return the first falsy value it finds.

1 && 0     // 0 is returned

The rule still applies If we start adding more and more operands using the AND operator. Let’s say we have 5 strings, in which none of them are empty strings. The result will be in returning the last string it finds as it will be a truthy value.

'Ford' && 'Chevrolet' && 'Jeep' && 'Honda' && 'Mazda'   // 'Mazda' is returned

If we make a little twist and add a falsy value such as an empty string, the AND operator will return the empty string as soon as it determines the operand is has a falsy value.

'Ford' && 'Chevrolet' && 'Jeep' && '' && 'Mazda'   // '' is returned

Efficient way to skip operands

If we add multiple falsy values to the previous example, the AND operator will return the first operand with a falsy value.

'Ford' && 0 && 'Jeep' && '' && 'Mazda' && false   // 0 is returned

This rather turns an efficient way to stop checking every operand as soon as it finds a falsy value. In these examples, it might be easier to make a change so we add the falsy values in the very beginning to stop checking for operands as soon as we can.

false && 0 && 'Jeep' && '' && 'Mazda' && false   // false is returned

Developers know that typically values are stored in variables and there is not always a way to tell if an operand will be truthy or falsy. However, if there is a good idea that certain functions or data retrieved from a database might return a falsy value, it might be a good idea to place that variable as the first operand.

variableWithHighChancesOfBeingFalsy && otherVariables

How OR (||) Operator Works

The logical operator OR (&&) returns the value of the first truthy operand it finds or the value of the last operand if all values are falsy.

In a similar way to using the AND (&&) operator, the way the logical operator || applies its logic is from left to right. Therefore, in the following snippet of code, OR operator will start determining first whether operand1 is truthy or falsy. If it is truthy it will return the value of operand1, otherwise, it will continue to check the next operand which is operand2, and determine whether it is truthy or false, and so on until it finds the first truthy value.

operand1 || operand2 || operand3

Given the following example where 1 and 2 are truthy values, the value of the first operand will be returned.

1 || 2     // 1 is returned

The rule still applies if we start adding more and more operands using the OR operator. Let’s say we have 5 numbers, in which none of them is 0 or a falsy value. The result will be in returning the first number it finds as it will be a truthy value.

1 || 2 || 3 || 4 || 5   // 1 is returned

If we make a little twist and add falsy values such as an empty string, false, and 0s, the OR operator will return the first truthy value it finds.

'' || 0 || false || 'Yes!'   // 'Yes!' is returned

In case the OR operator doesn’t find any truthy value, it returns the last operand value.

'' || 0 || false || null   // null is returned

Conclusion

All in all, AND and OR logical operators do not always return a boolean value (true or false), but instead the value of one of the two operands. Understanding what is an operand and recognizing between truthy and falsy values are key steps to get a good grasp of how AND and OR operators work.

Not knowing how these operators truly work leads to many unexpected bugs and errors for developers working with JavaScript, regardless of how many years they have been working with the programming language.

Now, next time you see some the following code:

const car = { brand: 'Ford', model: 'Mustang' };
const isCarMustang = car && car.model;

You are going to be able to say the value of isCarMustang is "Mustang" instead of true.

Quick challenge: What is the result of 0 && 1 && 2 || "foo" || "bar"?

Did you like this article?

Share your thoughts by replying on Twitter of Become A Better Programmer or to my personal Twitter account.