JavaScript logical operators explained

Two frequently used JavaScript operators are the && and || logical operators. Many developers are happy with the "it's true if both of them are true" and "if one of them is true, it will be true" type of use. However, these operators can do more than that.

I’m sure you are familiar with logical operators because you learned them in high school.

Let’s revise those concepts in a few paragraphs! This short summary will help you understand JavaScript logical operators.

and

Consider two simple statements and assume that both of them are true, independent of each other:

Statement A: It’s sunny today. Statement B: I’m feeling good.

Now concatenate them into one statement, and let’s call it a master statement:

It’s sunny today and I’m feeling good.

We feel that the master statement is true, since both statements, one by one, are true.

But if we negate one or both of the statements, the master statement becomes false.

Why? If we negate statement A, our master statement looks like this:

It’s not sunny today and I’m feeling good.

The word and indicates that both statement A and statement B must be true at the same time if we want our master statement to be true. and creates such a strong tie between the statements that the master statement immediately becomes false once we change the logical value (i.e. the truthiness or falseness of a statement) of either A or B or both to false.

or

Now we create a new master statement from statements A and B, this time we place the word or in between:

It’s sunny today or I’m feeling good.

Again, assume for a moment that both A and B are true: The Sun is shining and I’m feeling utterly awesome. In this case the master statement is also true.

What if we change the weather and say the following:

It’s not sunny today or I’m feeling good.

Am I lying when I declare that? No! The word or indicates that we have some freedom: One of the statements is still true, so negating statement A won’t change the logical value of the whole master statement. or is less strict than and.

If it’s still not clear why the master statement is true, consider the following:

I’ll give away a million dollars or I’ll blink at least once in the next five minutes.

Do I lie when I’m saying that?

No. Of course, I’m not fool, so I won’t give away a million dollars, I don’t even have the money, so the first statement was a big fat lie (hence the logical value of giving away a million dollars is unfortunately false). But the second part, the statement about blinking is true! It has already happened since I wrote that line, so I didn’t lie at all.

Back to the original problem: What if we change the logical value of both A and B? The master statement will look like this:

It’s not sunny today or I’m not feeling good.

Now this master statement is false, because however hard I’m trying to choose one true statement (either A or B), it’s not possible, both of them are false.

Now let’s have a look at how JavaScript manages logical operators.

The && operator

It’s commonly believed that the && operator is the and in JavaScript but this is only half of the truth.

It’s true though that a statement including && is only true if both left- and right-hand side operands are true:

const a = true;
const b = true;
console.log(a && b); // true

const c = false;
const d = true;
console.log(c && d); // false

const e = true;
const f = false;
console.log(e && f); //false

const g = false;
const h = false;
console.log(g && h); // false

So far so good, high school math is working well in practice.

But the && operator is more than that: It’s checking the logical value (i.e. true or false) of the first operand (statement) and if that evaluates to true, it will return the second operand. If the first operand can be converted to false, it will return the first operand.

This is best shown in the following snippet:

const firstNumber = 3;
const secondNumber = 5;
console.log(firstNumber && secondNumber); // 5

firstNumber is 3, which is a truthy value, so it’s converted to true. Because the first statement is true, the operator returns secondNumber, which is 5.

Similarly, if the logical value of the first operand is false, we’ll get it returned:

const falsyValue = 0;
console.log(falsyValue && secondNumber); // 0

Whatever the value of secondNumber is (5 in this case), the operator returns the first statement (and not necessarily false).

We could have written any falsy values instead of 0 as the first operand. For example, if we made falsyValue equal to undefined, the && operator would return undefined and not false.

The || operator

Similarly to &&, the || operator partly corresponds to the or word in that sense that the truthiness of only one of the statements is enough for the master statement to become true:

console.log(a || b); // true
console.log(c || d); // true
console.log(e || f); // true
console.log(g || h); // false

The || operator is also more than that. It checks the value of the first operand and if it’s truthy, it will return the first operand. If the first operand can be converted to false, it will return the second operand:

console.log(firstNumber || secondNumber); // 3
console.log(falsyValue || secondNumber); // 5

firstNumber is truthy (it’s value is 3), so it will be returned. In the second example, falsyValue is falsy, so the value of the second statement (secondNumber) will be returned, so we will get 5.

As it can be seen, && and || behave in the opposite way.

Combining them

These operators can also be combined. Due to operator precedence, the && is “stronger” than ||, which means that if both can be found in an expression, && should be read first:

const thirdNumber = 7;
console.log(firstNumber && secondNumber && thirdNumber); // 7
console.log(firstNumber && falsyValue && thirdNumber); // 0
console.log(firstNumber || secondNumber && thirdNumber); // 3
console.log(falsyValue || secondNumber && thirdNumber); // 7

The first example shows a case where all operands evaluate to truthy, so the returned value of the statement is thirdNumber, i.e. 7.

The second example contains a falsy value. The reading direction is from left to right, so we first evaluate firstNumber && falsyValue. firstNumber can be converted to true, so it returns the second operand (falsyValue), which is 0. We already have a falsy value in the expression. Although thirdNumber is truthy, it won’t change the result, so our second expression will return the falsy value (0).

In the third case the order of operators (operator precedence) suggests that we need to start with secondNumber && thirdNumber. Both are truthy, so this expression will evaluate to 5, the value of secondNumber. Now our expression is reduces to firstNumber || 5, we need to evaluate that expression, and since firstNumber is also truthy (3), the expression returns the first operand, i.e. 3.

The last example can be similarly evaluated. We take secondNumber && thirdNumber first. Both are truthy, so it returns second operand (thirdNumber, the value is 7). Now we can move on to the || operator by evaluating falsyValue || 7. The first operand (falsyValue) is falsy, so the expression will return the second operand, so we’ll get 7.

Changing the order

Can we override the operator precedence? Yes, if we place the “weaker” expression (||) in parentheses. Memories from math class may indicate that parentheses come first when we decide on the order of numerical operations either.

The same applies here. All we have to do is to put the || in parentheses:

console.log(falsyValue && secondNumber || thirdNumber); // 7
console.log(falsyValue && (secondNumber || thirdNumber)); // 0

In the first example, we take falsyValue && secondNumber first, it returns falsyValue (0). The problem has been reduced to evaluate 0 || thirdNumber, and this will return thirdNumber (7).

In the second example, however, we override the operator precedence, and we need to take secondNumber || thirdNumber first. Both are truthy, so we’ll get secondNumber (5) returned. Evaluating falsyValue && 5 will result in the value of the first operand (since it’s falsy), i.e. 0.

Short circuit

The behavior of these operators makes it possible to do the so-called “short-circuit”. Because of the logic of the && and || operators, whatever the second operand is, the following expressions are always evaluated to false and true, respectively:

console.log(false && { name: 'Alice' }); // false
console.log(true || { name: 'Alice' }); // true

We could have written anything instead of Alice’s object, the first expression will always be false and the second will always be true.

Conclusion

The && and || logical operators are important tools in the toolkit of the JavaScript developer. Knowing the subtleties of these operators will help exploit all of their features and write more seamless and elegant code.

Enjoy coding!