When an expression has several operators, JavaScript needs a rule for which one goes first. You know it from school maths: multiplication comes before addition.
console.log(2 + 3 * 4); // → 14
console.log((2 + 3) * 4); // → 20
That rule is operator precedence. Parentheses override it.
The order that matters most
From highest priority to lowest (a simplified list):
- Parentheses
( ) - Member access and calls:
.,[],() - Unary:
!,typeof,-x,++ - Exponent
** - Multiply and divide:
*,/,% - Add and subtract:
+,- - Comparison:
<,>,<=,>= - Equality:
===,!== &&||and??- Ternary
? : - Assignment
=,+=, …
const a = 5;
console.log(a + 2 > 6 && a < 10); // → true
// The maths first, then the comparisons, then &&
Associativity
When operators have the same level, associativity decides the direction. Most go left to right. A few go right to left, for example ** and assignment:
console.log(2 ** 3 ** 2); // → 512 (3 ** 2 first = 9, then 2 ** 9)
console.log(10 - 4 - 3); // → 3 (left to right)
Where beginners get caught
const price = 20;
console.log("Total: " + price + 5); // → Total: 205
console.log("Total: " + (price + 5)); // → Total: 25
Both + operators have the same level and go left to right. The string joins first, so the 5 is added as text.
console.log(!true || true); // → true ((!true) || true)
console.log(!(true || true)); // → false
The simple rule
You do not need to memorise the table. Add parentheses whenever the order is not obvious. They cost nothing and tell the next reader what you meant. Mixing && and ||, or ?? with others, deserves parentheses every time.