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 (??).
| Operator | Name | Result |
|---|---|---|
a && b | Logical AND | Returns a when a is falsy. Otherwise, returns b. |
a || b | Logical OR | Returns a when a is truthy. Otherwise, returns b. |
!a | Logical NOT | Converts a to a Boolean, then returns the opposite Boolean. |
a ?? b | Nullish coalescing | Returns 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:
A | B | A && B | A || B | !A |
|---|---|---|---|---|
true | true | true | true | false |
true | false | false | true | false |
false | true | false | true | true |
false | false | false | false | true |
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:
false0and-00n"",'', and an empty template stringnullundefinedNaN
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:
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.
true && true; // true true && false; // false "ready" && 42; // 42 "ready" && 42 && null; // null
Use && when every condition must pass:
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:
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.
false || true; // true "" || "Fallback"; // "Fallback" 0 || null || "Last value"; // "Last value" 0 || false || ""; // ""
This behavior makes || useful when any condition can pass:
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”:
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.
!true; // false !0; // true !"ready"; // false !null; // true
Two NOT operators convert a value to its Boolean equivalent:
!!"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 && bskipsbwhenais falsy.a || bskipsbwhenais truthy.a ?? bskipsbwhenais neithernullnorundefined.
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:
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.
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 input | input || "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:
!&&||
This expression:
hasToken || isGuest && hasInvite;
is evaluated as:
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 ||:
null || undefined ?? "fallback"; // SyntaxError
Group the expression explicitly:
(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.
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.
Related logical assignment operators
JavaScript also provides &&=, ||=, and ??=. They update the left side only when the matching logical operator would evaluate its right side.
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 inBoolean(...)when you require a Boolean. - Using
||when valid data can be falsy. A count of0, an empty string, orfalsewill 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
ifwhen 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.



