Operators and Expressions
What this domain covers
Precedence, associativity, short-circuiting, and the coercion behaviour of each operator. Expect snippets that mix +, ==, ??, and unary operators on operands of different types.
Arithmetic and increment
+ - * / % **. Remainder keeps the sign of the dividend: -7 % 3 === -1. ** is right-associative and forbids an unparenthesised unary minus on its left (-2 ** 2 is a SyntaxError). Postfix x++ yields the old value; prefix ++x yields the new one. Unary + is the idiomatic ToNumber converter.
Equality
=== compares without conversion (but NaN !== NaN and +0 === -0). == coerces with fixed rules: null == undefined is true; null == 0 is false; '1' == 1 is true; true == 1 is true; [] == false is true because both sides reduce to '' and 0. Object versus primitive triggers ToPrimitive on the object.
Logical and nullish
&& and || return an operand, not a boolean: 0 || 'x' is 'x'. ?? falls back only for null/undefined, so 0 ?? 'x' is 0. Mixing ?? with || or && without parentheses is a SyntaxError. ?. short-circuits the whole chain when its base is nullish. Compound forms include +=, ??=, ||=, &&=.
Worked example
let n = 0;
console.log(n || 'default', n ?? 'default');
console.log(3 > 2 > 1);
Reasoning: || treats 0 as falsy โ 'default'; ?? only checks nullishness โ 0. The second line compares left to right: 3 > 2 is true, then true > 1 converts true to 1, and 1 > 1 is false.
Traps
- Assuming
&&/||produce booleans and then calling.lengthon the result. - Using
||as a default when0or''are valid inputs - use??instead. - Reading
1 < 2 < 3as a chained comparison; it is two separate comparisons. - Ternary binds tighter than assignment but looser than comparison.