JavaScript Logical Operators: &&, ||, !, and ??

Logical and equality operators in JavaScript
Logical and equality operators in JavaScript

JavaScript logical operators do more than combine true and false conditions. They select values, skip work through short-circuiting, and can quietly replace valid data when used for defaults. You will learn exactly how &&, ||, !, and ?? behave, with concrete examples and the edge cases worth remembering.

Logical operators in JavaScript at a glance

Logical operators let JavaScript combine conditions and select values. The four operators you will use most are logical AND (&&), logical OR (||), logical NOT (!), and nullish coalescing (??).

OperatorNameResult
a && bLogical ANDReturns a when a is falsy. Otherwise, returns b.
a || bLogical ORReturns a when a is truthy. Otherwise, returns b.
!aLogical NOTConverts a to a Boolean, then returns the opposite Boolean.
a ?? bNullish coalescingReturns b only when a is null or undefined. Otherwise, returns a.

The ECMAScript evaluation rules define &&, ||, and ?? as value-selecting, short-circuit operators. This detail matters: && and || do not always return true or false. They return one of their operands.

With Boolean operands, the familiar truth table still applies:

ABA && BA || B!A
truetruetruetruefalse
truefalsefalsetruefalse
falsetruefalsetruetrue
falsefalsefalsefalsetrue

Truthy and falsy values

JavaScript converts an operand to a Boolean when it decides whether to continue evaluating a logical expression. A value that converts to true is truthy. A value that converts to false is falsy.

The standard falsy values are:

  • false
  • 0 and -0
  • 0n
  • "", '', and an empty template string
  • null
  • undefined
  • NaN

All other ordinary JavaScript values are truthy. That includes empty arrays, empty objects, and the string "false". The browser-only document.all object is a historical exception and is also falsy.

Use Boolean(...) to see how a value converts:

JavaScript
Boolean(0); // false Boolean(""); // false Boolean("false"); // true Boolean([]); // true Boolean({}); // true

These conversion rules explain the behavior of every logical operator that follows.

Logical AND (&&)

Logical AND evaluates operands from left to right. It returns the first falsy operand it finds. If every operand is truthy, it returns the last operand.

JavaScript
true && true; // true true && false; // false "ready" && 42; // 42 "ready" && 42 && null; // null

Use && when every condition must pass:

JavaScript
const isSignedIn = true; const role = "editor"; const hasDraft = true; const canPublish = isSignedIn && role === "editor" && hasDraft; console.log(canPublish); // true

You can also guard an access or call:

JavaScript
const profile = null; const displayName = profile && profile.name; console.log(displayName); // null

Here, JavaScript never evaluates profile.name because profile is falsy. Optional chaining, as in profile?.name, usually states this property-access intent more directly.

Logical OR (||)

Logical OR also evaluates from left to right. It returns the first truthy operand it finds. If every operand is falsy, it returns the last operand.

JavaScript
false || true; // true "" || "Fallback"; // "Fallback" 0 || null || "Last value"; // "Last value" 0 || false || ""; // ""

This behavior makes || useful when any condition can pass:

JavaScript
const isOwner = false; const isEditor = true; const canEdit = isOwner || isEditor; console.log(canEdit); // true

It also supports fallback chains when all falsy values mean “missing”:

JavaScript
const nickname = ""; const fullName = "Ada Lovelace"; const label = nickname || fullName || "Anonymous"; console.log(label); // "Ada Lovelace"

Logical NOT (!)

Logical NOT converts its operand to a Boolean and reverses it. Unlike && and ||, ! always returns a Boolean.

JavaScript
!true; // false !0; // true !"ready"; // false !null; // true

Two NOT operators convert a value to its Boolean equivalent:

JavaScript
!!"ready"; // true !!0; // false

Boolean(value) communicates the same conversion more explicitly. Use ! when you need to reverse a condition, and use Boolean(...) when conversion is the main point.

How short-circuit evaluation works

The binary logical operators evaluate the left operand first. They evaluate the right operand only when it can affect the result:

  • a && b skips b when a is falsy.
  • a || b skips b when a is truthy.
  • a ?? b skips b when a is neither null nor undefined.
JavaScript
let calls = 0; function loadSettings() { calls += 1; return { theme: "dark" }; } false && loadSettings(); // skipped true || loadSettings(); // skipped undefined ?? loadSettings(); // called console.log(calls); // 1

Short-circuiting is useful for guarded function calls:

JavaScript
if (isReady) { startJob(); }

You could write isReady && startJob(), but an if statement makes the side effect obvious. Reserve compact logical expressions for cases where they stay easy to read.

|| versus ?? for default values

Use || when every falsy value should trigger the fallback. Use ?? when only null and undefined mean that a value is absent.

JavaScript
const configuredRetries = 0; const retriesWithOr = configuredRetries || 3; const retriesWithNullish = configuredRetries ?? 3; console.log(retriesWithOr); // 3 console.log(retriesWithNullish); // 0

The distinction applies to false and empty strings too:

Value of inputinput || "default"input ?? "default"
0"default"0
false"default"false
"""default"""
null"default""default"
undefined"default""default"

The ?? operator is usually the correct defaulting choice when 0, false, or "" are valid application data.

Operator precedence and grouping

JavaScript evaluates logical NOT before logical AND, and logical AND before logical OR:

  1. !
  2. &&
  3. ||

This expression:

JavaScript
hasToken || isGuest && hasInvite;

is evaluated as:

JavaScript
hasToken || (isGuest && hasInvite);

Add parentheses when they make the intended grouping easier to see, even when the default operator precedence already produces the result you want.

JavaScript rejects an unparenthesized mix of ?? with && or ||:

JavaScript
null || undefined ?? "fallback"; // SyntaxError

Group the expression explicitly:

JavaScript
(null || undefined) ?? "fallback"; // "fallback"

A practical example with several conditions

The function below combines a nullish default with AND and OR conditions. A configured limit of 0 remains valid and disables new sessions.

JavaScript
function canStartSession(user, config) { const maxSessions = config.maxSessions ?? 1; const hasAllowedRole = user.role === "agent" || user.role === "admin"; const hasCapacity = user.activeSessions < maxSessions; return user.isAuthenticated && hasAllowedRole && hasCapacity; } const user = { isAuthenticated: true, role: "agent", activeSessions: 0, }; console.log(canStartSession(user, { maxSessions: 2 })); // true console.log(canStartSession(user, { maxSessions: 0 })); // false

Each intermediate name states one business rule. The final return value then reads as a compact list of requirements.

JavaScript also provides &&=, ||=, and ??=. They update the left side only when the matching logical operator would evaluate its right side.

JavaScript
settings.timeout ??= 5000; // assign if null or undefined cache.value ||= computeValue(); // assign if cache.value is falsy job.enabled &&= account.active; // assign if job.enabled is truthy

Choose among them with the same truthy, falsy, and nullish rules as &&, ||, and ??.

Common logical-operator mistakes

  • Assuming && and || return Booleans. They return operand values. Wrap the expression in Boolean(...) when you require a Boolean.
  • Using || when valid data can be falsy. A count of 0, an empty string, or false will be replaced. Use ?? when only missing values need a default.
  • Hiding side effects in the right operand. Short-circuiting may prevent a function call or assignment from running. Prefer an explicit if when that work matters.
  • Confusing logical, bitwise, and equality operators. &&, ||, and ! are logical operators. &, |, and ~ operate on bits. == and === compare values.

For arithmetic, assignment, comparison, and other operator categories, see our JavaScript operators overview.

Frequently asked questions

Do && and || return Booleans?

They return one of their operands. If both operands are Boolean, the returned operand is also Boolean. With other values, the result may be a string, number, object, null, or another value. Use Boolean(expression) when you need an explicit Boolean result.

Is == a logical operator in JavaScript?

No. == is the loose equality operator. It compares two values after permitted type conversions and returns a Boolean. Logical operators combine or invert conditions and select operand values.

Which runs first, && or ||?

&& has higher precedence than ||, so JavaScript groups the AND expression first. Logical NOT (!) has higher precedence than both. Parentheses are the clearest way to show a reader which conditions belong together.

Share

Subscribe

Sign up to our e-mail list to get the best of the Dasha blog sent directly to your inbox.

We use cookies for functional and analytical purposes. Please refer to our Privacy Policy for details.