Logical operators
In everyday speech we join conditions all the time: "if there is a ticket and a passport", "if it rains or snows". A program has three logical operators for this: && ("and"), || ("or") and ! ("not").
Each of them builds an expression: code that has a value, such as a + b, 42 or the call Math.floor(2.5). With the values true and false, the logical operators work as in logic. The expression a && b gives true only when both values are true, and a || b when at least one is. But && and || accept values of any type, and their result is not necessarily a boolean:
console.log(true && false, true || false, !true); // false true false
console.log("Ann" || "guest"); // Ann
console.log("" || "guest"); // guest
console.log(0 && "never"); // 0
console.log(false && true || true); // trueLet's walk through what was printed:
- The first line is ordinary logic:
false true false. "Ann" || "guest"returnedAnn, the left value itself, nottrue."" || "guest"returnedguest: the operator skipped the empty string.0 && "never"returned0, and"never"was never reached.- The last line prints
true; we will see why below.
Both operators return one of the two values they stand between.
What && and || return
To choose which value to return, && and || check the left one as if it were a boolean. In this check, exactly eight values are falsy:
false;0,-0and0n;- the empty string
""; nullandundefined;NaN.
Minus zero -0 comes, for example, from -1 * 0, and 0n is zero of type bigint: the letter n at the end marks that type. All other values are truthy, for example "guest" and 42.
Each operator chooses its result in its own way:
||returns the left value if it is truthy, and the right one otherwise;&&returns the left value if it is falsy, and the right one otherwise;!always gives aboolean:!0givestrue, and!"Ann"givesfalse.
A handy picture for || is a guest's name badge at the door. If the guest gave a name, the badge shows the name; if not, it shows "guest". And && is like a row of turnstiles: you stop at the first closed one, and that one becomes the result.
If all the turnstiles are open, the result is the last one: 5 && 1 gives 1. That is where the picture ends: a real turnstile only lets you through or not, while && returns the value itself.
First &&, then ||
In one expression && runs before ||, as * runs before +. So the last line of the first program reads as (false && true) || true:
false && truegivesfalse;false || truegivestrue.
Parentheses make the order explicit: (a && b) || c. Use them when both operators meet in one expression: it is easier to read that way.
Short circuit
If the left value is enough for the answer, the right one is not even evaluated. This is called short-circuit evaluation. The turnstiles work the same way: if the first one is closed, nobody walks to the second. || stops after a truthy value, and && stops after a falsy one:
function loud() {
console.log("called");
return 1;
}
console.log(1 || loud()); // 1
const x = 0 || loud(); // called
console.log(x); // 1In the line 1 || loud() the function loud does not run: the left side of || already holds the truthy 1. In the line 0 || loud() the left 0 is falsy, so loud runs: it prints called and returns 1, which goes into x.
&& mirrors this: it evaluates the right side only after a truthy left value. Step through the program below and watch when a loud frame appears above the script frame: only then is the right side really evaluated.
1function loud() {2 console.log("called");3 return 1;4}5 6const a = 1 || loud();7console.log(a);8const b = 0 || loud();9console.log(b);10const c = 0 && loud();11console.log(c);12const d = 5 && loud();13console.log(d);
The left 1 is truthy, so || returns it at once and does not call loud().
Interviewers often ask this: what do && and || return, and will the function on the right be called? The answer: the operator returns one of the two values, and the right side is evaluated only when the left one is not enough for the answer.
The ?? operator
The ?? operator is like ||, but it returns the right value only when the left one is null or undefined. It is called the nullish coalescing operator. On the guest's badge it writes "guest" only if the name field is missing altogether. The values 0, "" and false are neither null nor undefined, so ?? keeps them:
console.log(0 || 10, 0 ?? 10); // 10 0
console.log(null ?? 10, undefined ?? 10); // 10 10
console.log(false ?? true); // falseLine by line:
0 || 10gives10, because0is falsy, while0 ?? 10keeps0.??replacesnullandundefinedwith10.false ?? truegivesfalse: it is a real value, not a missing one.
Mixing ?? with || or && without parentheses is not allowed: such a line is a syntax error. With parentheses it works: (a || b) ?? c.
Common mistake
A default value is set with ||, although 0 is a valid value:
const volume = 0;
const shown = volume || 50; // ✗
console.log(shown); // 50The volume 0 is falsy, so || replaced it with 50. When only a missing value should be replaced, write volume ?? 50: the result is 0.
Key points
||returns the left value if it is truthy, otherwise the right one;&&returns the left value if it is falsy, otherwise the right one.- The right side is evaluated only when the left one is not enough for the answer: this is short circuit.
&&runs before||, and??mixes with them only through parentheses.??replaces onlynullandundefined, while||replaces any falsy value, even0and"".
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.