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.
Table of Contents
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 0
s, 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.