JavaScript Operator Precedence Rules Explained
JavaScript operator precedence determines the sequence in which operators are parsed and evaluated within an expression. Understanding these rules is essential for writing predictable code, avoiding subtle logic bugs, and knowing when to use grouping parentheses to override default evaluation behavior. This guide outlines the core hierarchy of operator precedence, associativity rules, and common evaluation patterns in JavaScript.
Understanding Precedence and Associativity
When an expression contains multiple operators, JavaScript uses two mechanisms to resolve the evaluation order:
- Precedence: Operators with higher precedence are
evaluated before operators with lower precedence. For example, in
3 + 4 * 2, the multiplication operator (*) has higher precedence than addition (+), resulting in3 + 8 = 11. - Associativity: When operators have the same
precedence level, associativity determines the direction of evaluation:
- Left-to-Right (Left-associative): The expression is
resolved from left to right (e.g.,
a - b - cevaluates as(a - b) - c). - Right-to-Left (Right-associative): The expression
is resolved from right to left (e.g.,
a = b = cevaluates asa = (b = c), and2 ** 3 ** 2evaluates as2 ** (3 ** 2)).
- Left-to-Right (Left-associative): The expression is
resolved from left to right (e.g.,
Operator Precedence Hierarchy
The table below lists JavaScript operators ordered from highest precedence (evaluated first) to lowest precedence (evaluated last):
| Precedence Level | Operator Type | Syntax Examples | Associativity |
|---|---|---|---|
| 19 (Highest) | Grouping | ( ... ) |
N/A |
| 18 | Member Access / Calls | obj.prop,
obj[prop], fn(), new fn() |
Left-to-right |
| 17 | Optional Chaining / new (no
args) |
obj?.prop,
new fn |
Left-to-right |
| 16 | Postfix Increment / Decrement | x++, x-- |
N/A |
| 15 | Prefix / Logical NOT / Unary / Type | ++x, --x,
!x, +x, -x, typeof,
void, delete, await |
Right-to-left |
| 14 | Exponentiation | ** |
Right-to-left |
| 13 | Multiplicative | *, /,
% |
Left-to-right |
| 12 | Additive | +, - |
Left-to-right |
| 11 | Bitwise Shift | <<,
>>, >>> |
Left-to-right |
| 10 | Relational / Type Testing | <, <=,
>, >=, in,
instanceof |
Left-to-right |
| 9 | Equality | ==, !=,
===, !== |
Left-to-right |
| 8 | Bitwise AND | & |
Left-to-right |
| 7 | Bitwise XOR | ^ |
Left-to-right |
| 6 | Bitwise OR | \| |
Left-to-right |
| 5 | Logical AND | && |
Left-to-right |
| 4 | Logical OR / Nullish Coalescing | \|\|, ?? |
Left-to-right |
| 3 | Conditional (Ternary) | condition ? val1 : val2 |
Right-to-left |
| 2 | Assignment / Logical Assignment | =, +=,
-=, **=, &&=,
\|\|=, ??= |
Right-to-left |
| 1 (Lowest) | Comma | , |
Left-to-right |
Key Precedence Rules to Remember
1. Logical Operators Follow a Strict Hierarchy
Logical NOT (!) runs before Logical AND
(&&), which runs before Logical OR
(||):
const result = !false && false || true;
// Step 1: (!false) -> true
// Step 2: (true && false) -> false
// Step 3: (false || true) -> true2. Nullish Coalescing
(??) and Logical Operators
JavaScript explicitly forbids combining ?? directly with
&& or || without explicit parentheses
to prevent ambiguity. Doing so throws a SyntaxError:
// SyntaxError:
// const value = a || b ?? c;
// Correct usage:
const value = (a || b) ?? c;3. Exponentiation is Right-Associative
Unlike most arithmetic operators, exponentiation executes from right to left:
const result = 2 ** 2 ** 3;
// Evaluates as 2 ** (2 ** 3) -> 2 ** 8 = 256
// Not (2 ** 2) ** 3 -> 4 ** 3 = 644. Assignment Has Low Precedence
Assignment operators are near the bottom of the precedence table,
ensuring expressions to the right of the = operator are
fully computed before the variable receives the value:
let total;
total = 10 + 5 * 2;
// 5 * 2 = 10 -> 10 + 10 = 20 -> total = 20Best Practice: Use Parentheses for Clarity
While memorizing the precedence table is useful, relying on implicit
precedence in complex expressions makes code harder to read and
maintain. Wrapping sub-expressions in parentheses (())
clearly communicates intent and removes ambiguity for both the
JavaScript engine and future maintainers.