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.

aba || b
truetruetrue
falsetruetrue
truefalsetrue
falsefalsefalse
OR truth table: the result is true unless both operands are 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 — not true, 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.

null
falsy → skip
0
falsy → skip
1
truthy → stop, return 1
null || 0 || 1 — scanning left to right for the first truthy value.

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:

interactiveThe || fallback chain

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.

true
||
alert(“not printed”)
← never reached
false
||
alert(“printed”)
← runs
Short-circuit: a truthy left operand stops evaluation before the right operand runs.

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:

interactiveShort-circuit: does the right side run?

&& (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
aba && b
truetruetrue
falsetruefalse
truefalsefalse
falsefalsefalse
AND truth table: the result is true only when both operands are true.

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.

|| (OR)
returns first truthy
else the last value
&& (AND)
returns first falsy
else the last value
OR stops at the first truthy value; AND stops at the first falsy value.

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:

  1. Converts the operand to a boolean (true or false).
  2. 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.

“non-empty string”
— ! →
false
— ! →
true
!!value — the first NOT converts and inverts, the second inverts back to a pure boolean.

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:

interactiveTruthy or falsy? Click to test !!value

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.