Logical operators
JavaScript has four logical operators: || (OR), && (AND), ! (NOT), and ?? (Nullish Coalescing). This article covers the first three. The ?? operator gets its own article next.
The name “logical” is a little misleading. You can feed these operators values of any type, not only true and false, and what comes back can also be any type. That flexibility is where most of their real-world usefulness lives.
|| (OR)
The OR operator is written as two vertical bars:
result = a || b;
In the classic textbook definition, OR works only on booleans. If either operand is true, the result is true; otherwise false. JavaScript keeps that behavior and then adds more on top. Start with the pure-boolean case.
There are four possible combinations:
alert( true || true ); // true
alert( false || true ); // true
alert( true || false ); // true
alert( false || false ); // false
The only way to get false is when both sides are false. Any single true is enough.
| a | b | a || b |
|---|---|---|
| true | true | true |
| false | true | true |
| true | false | true |
| false | false | false |
When an operand isn’t a boolean, JavaScript converts it to one for the test. So the number 1 counts as true, and 0 counts as false:
if (1 || 0) { // reads like if (true || false)
alert( 'truthy!' );
}
The most common place you’ll reach for OR is inside an if, to check whether any of several conditions holds. Here’s an opening-hours check — the pool is closed before 7 or after 21:
let hour = 9;
if (hour < 7 || hour > 21) {
alert( 'The pool is closed.' );
}
You can chain as many conditions as you need:
let hour = 12;
let isHoliday = true;
if (hour < 7 || hour > 21 || isHoliday) {
alert( 'The pool is closed.' ); // it is a holiday
}
Even though hour sits comfortably inside opening hours, isHoliday is true, so the whole condition is true.
OR “||” finds the first truthy value
Everything above is the classical view. Now the part that makes || genuinely useful in JavaScript.
Given a chain of OR’ed values:
result = value1 || value2 || value3;
The || operator walks through them like this:
- Evaluate operands left to right.
- Convert each one to a boolean. The moment one converts to
true, stop and return that operand’s original value — nottrue, the actual value. - If every operand converted to
false, return the last one.
The key detail: the value comes back in its original form. No conversion is applied to what’s returned.
So a chain of || gives you the first truthy value, or the last value if they’re all falsy.
Watch it in action:
alert( 1 || 0 ); // 1 (1 is truthy)
alert( null || 1 ); // 1 (1 is the first truthy value)
alert( null || 0 || 1 ); // 1 (the first truthy value)
alert( undefined || null || 0 ); // 0 (all falsy, returns the last value)
That last line is worth staring at. Everything is falsy, so || runs out of options and hands back the final operand, 0. It doesn’t return false — it returns whatever the last value literally was.
This opens up two patterns you’ll see constantly.
1. Getting the first truthy value from a list
Say you have customName, profileName, and handle, all optional and possibly empty. You want to display whichever one has data, falling back to "Guest" if none do:
let customName = "";
let profileName = "";
let handle = "pixelDrifter";
alert( customName || profileName || handle || "Guest" ); // pixelDrifter
Empty strings are falsy, so || skips past customName and profileName, lands on handle (a non-empty string, truthy), and stops. If all three had been empty, the chain would fall through to "Guest".
Try it live. Clear the fields to make them falsy, or type something in — the display name is whichever field is the first non-empty one, with "Guest" as the final fallback:
2. Short-circuit evaluation
|| stops as soon as it finds a truthy value. It never even looks at the operands to the right. This is called short-circuit evaluation.
It barely matters when operands are plain values, but it matters a lot when an operand is an expression with a side effect — a function call, an assignment, anything that does something.
true || alert("not printed");
false || alert("printed");
On the first line, || sees true, immediately returns, and never evaluates the alert. On the second line, false isn’t enough to stop, so evaluation continues to the alert, which runs. People sometimes use this to run a command only when the left side is falsy.
Here the right-hand side is a real side effect: it appends a line to a log. Flip the left operand between true and false and watch whether the right side ever runs:
&& (AND)
The AND operator is two ampersands:
result = a && b;
Classically, AND returns true only when both operands are truthy, and false otherwise:
alert( true && true ); // true
alert( false && true ); // false
alert( true && false ); // false
alert( false && false ); // false
| a | b | a && b |
|---|---|---|
| true | true | true |
| false | true | false |
| true | false | false |
| false | false | false |
An example with if, requiring two conditions at once:
let hour = 9;
let minute = 45;
if (hour == 9 && minute == 45) {
alert( 'The time is 9:45' );
}
As with OR, any value is allowed as an operand:
if (1 && 0) { // evaluated as true && false
alert( "won't work, because the result is falsy" );
}
AND “&&” finds the first falsy value
Given a chain of AND’ed values:
result = value1 && value2 && value3;
The && operator does the mirror image of ||:
- Evaluate operands left to right.
- Convert each to a boolean. The moment one converts to
false, stop and return that operand’s original value. - If every operand converted to
true, return the last one.
Put simply: AND returns the first falsy value, or the last value if all are truthy. OR looks for the first truthy value; AND looks for the first falsy one. Same machinery, opposite target.
Some examples:
// first operand is truthy,
// so AND returns the second operand:
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5
// first operand is falsy,
// so AND returns it and ignores the rest:
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0
Chaining several in a row, the first falsy value wins:
alert( 1 && 2 && null && 3 ); // null
When they’re all truthy, the last one comes back:
alert( 1 && 2 && 3 ); // 3, the last one
! (NOT)
The boolean NOT operator is a single exclamation mark:
result = !value;
It takes one argument and does two things:
- Converts the operand to a boolean (
trueorfalse). - Returns the opposite.
alert( !true ); // false
alert( !0 ); // true
A double NOT, !!, is a common shorthand for converting any value to its boolean equivalent:
alert( !!"non-empty string" ); // true
alert( !!null ); // false
The first ! converts the value to a boolean and flips it; the second ! flips it back. The net effect is a plain value-to-boolean conversion.
The built-in Boolean function does exactly the same conversion, just more explicitly:
alert( Boolean("non-empty string") ); // true
alert( Boolean(null) ); // false
Both approaches are fine. !! is compact and idiomatic; Boolean(...) spells out what you mean. Pick whichever reads better in context.
Click any value below to see its boolean form. The six falsy values flip to false; everything else is truthy:
NOT has the highest precedence of the logical operators, so it always runs first — before any && or ||. In !a && b, the ! applies to a alone, giving (!a) && b.