JavaScript Operator Precedence: How Expressions Are Evaluated
JavaScript operator precedence determines which part of an expression is evaluated first when multiple operators appear together. Understanding it helps you read code correctly, avoid logic bugs, and write expressions that do exactly what you intend.
Quick answer: Operators with higher precedence are evaluated before operators with lower precedence. When two operators have the same precedence, JavaScript uses associativity rules, and parentheses can always be used to make the order explicit.
Difficulty: Beginner
You'll understand this better if you know: basic variables, common JavaScript operators, and how expressions produce values.
1. What Is JavaScript Operator Precedence?
Operator precedence is the set of rules JavaScript uses to decide the evaluation order inside an expression. It matters whenever you combine operators such as +, *, &&, =, or ?: in one line.
- Higher-precedence operators run first.
- Operators with the same precedence follow associativity rules.
- Parentheses override the default order.
- Precedence affects how an expression is grouped, not necessarily the order of every side effect.
For example, in 2 + 3 * 4, multiplication happens before addition, so the result is 14, not 20.
2. Why JavaScript Operator Precedence Matters
Precedence is important because JavaScript code often looks straightforward while hiding a non-obvious evaluation order. If you do not know the rules, you can easily write expressions that compile successfully but produce the wrong result.
It matters most when you are combining:
- Arithmetic operators in calculations
- Comparison operators in conditional logic
- Logical operators in complex conditions
- Assignment with expressions
- Unary operators like !, typeof, and -
It also matters for readability. Even if you know the precedence table by heart, explicit grouping with parentheses makes your intent easier to understand for other developers and for your future self.
3. Basic Syntax or Core Idea
JavaScript does not have a special syntax for precedence. Instead, precedence is part of how expressions are interpreted by the language engine. You write a normal expression, and JavaScript groups the operators according to its rules.
Minimal example
This example shows the default order and how parentheses change it.
const result1 = 2 + 3 * 4;
const result2 = (2 + 3) * 4;
console.log(result1); // 14
console.log(result2); // 20In the first line, multiplication has higher precedence than addition, so 3 * 4 is calculated first. In the second line, parentheses force JavaScript to add first.
Associativity matters when precedence is equal
When two operators share the same precedence, associativity decides the grouping. Most arithmetic operators are left-to-right, while assignment is right-to-left.
const a = 10 - 3 - 2;
// Grouped as: (10 - 3) - 2 = 5
let x, y, z;
x = y = z = 5;
// Grouped as: x = (y = (z = 5))This means the same operator can still behave differently depending on whether JavaScript groups it left-to-right or right-to-left.
4. Step-by-Step Examples
The best way to learn precedence is to read expressions from the operator hierarchy instead of left to right. The following examples show common patterns you will see in real code.
Example 1: Arithmetic
Multiplication, division, and remainder are evaluated before addition and subtraction.
const total = 10 + 6 / 2;
// 10 + 3 = 13Because division has higher precedence than addition, JavaScript calculates 6 / 2 first.
Example 2: Comparison and arithmetic together
Comparisons happen after arithmetic, so the arithmetic result is compared as a whole.
const isValid = 4 + 2 > 5;
// (4 + 2) > 5 = trueThis is a common pattern in conditions that validate thresholds, limits, or ranges.
Example 3: Logical operators
&& has higher precedence than ||, so AND groups before OR.
const canEnter = isMember || hasTicket && isOpen;
// Grouped as: isMember || (hasTicket && isOpen)If you mean a different grouping, use parentheses. Many bugs in access rules and feature flags come from assuming left-to-right evaluation is enough.
Example 4: Unary operators
Unary operators such as ! and typeof apply before most binary operators.
const flag = !true && false;
// Grouped as: (!true) && false = false
const kind = typeof "hello" === "string";
// Grouped as: (typeof "hello") === "string" = trueHere, the unary operator produces a value first, and then the comparison uses that value.
5. Practical Use Cases
Operator precedence is most useful in everyday code where brevity and correctness must both be maintained. These are common situations where it shows up naturally:
- Form validation rules that combine multiple checks
- Pricing calculations with discounts, taxes, and rounding
- Access control logic based on role, status, and feature flags
- Boolean expressions in if statements and ternary expressions
- Data transformation code that combines null checks and property access
In practice, precedence helps you decide whether an expression can stay compact or should be split into smaller variables for clarity.
6. Common Mistakes
Mistake 1: Reading expressions strictly left to right
Beginners often assume JavaScript evaluates every operator in the order it appears. That assumption leads to incorrect expectations for calculations and conditions.
Problem: Multiplication is evaluated before addition, so this expression does not produce the sum from left to right.
const value = 10 + 2 * 3;
// 16, not 36Fix: Add parentheses if you want the addition first.
const value = (10 + 2) * 3;
// 36The corrected version works because parentheses force the grouping you intended.
Mistake 2: Mixing && and || without grouping
Logical expressions are especially easy to misread. Because && binds tighter than ||, the condition may not mean what you think it means.
Problem: This check grants access if the user is a member, or if they have a ticket and the event is open. That may be correct, but many developers intend a different rule.
const allowed = isMember || hasTicket && isOpen;Fix: Make the intended grouping obvious with parentheses.
const allowed = (isMember || hasTicket) && isOpen;The corrected version is safer because it documents the exact logic instead of relying on precedence knowledge.
Mistake 3: Expecting assignment to behave like comparison
One of the most common beginner bugs is writing = when comparison was intended. Assignment has very low precedence, so the expression may compile but behave incorrectly.
Problem: This line assigns a value instead of checking it. In many cases, the condition becomes the assigned value, which is not what you meant.
let count = 3;
if (count = 0) {
console.log("empty");
}Fix: Use strict equality when you want a comparison.
let count = 3;
if (count === 0) {
console.log("empty");
}The corrected version works because === compares values instead of overwriting them.
7. Best Practices
Practice 1: Use parentheses to communicate intent
Even if you know the precedence rules, the next developer may not immediately see your intended grouping. Parentheses make complex expressions self-documenting.
const shouldShow = isAdmin && (isVerified || hasOverride);This version is easier to maintain than relying on the reader to remember operator precedence.
Practice 2: Split long expressions into named variables
When an expression starts combining several operators, break it into smaller steps. This improves readability and makes debugging easier.
const subtotal = itemsTotal - discount;
const tax = subtotal * taxRate;
const grandTotal = subtotal + tax;Breaking the calculation into steps reduces precedence-related mistakes and makes each business rule easier to review.
Practice 3: Be careful with side effects inside expressions
Precedence tells you how JavaScript groups operators, but it does not make expressions with side effects easier to understand. Avoid hiding state changes inside complex expressions.
let index = 0;
const nextValue = values[index ++];Here, the increment operator works correctly, but combining it with other operations can make the flow hard to follow. Prefer clearer steps when the order of effects matters.
8. Limitations and Edge Cases
- Precedence does not always describe evaluation of side effects. Some expressions are grouped one way but still involve short-circuit behavior for logical operators.
- && and || return one of their operands, not necessarily a strict boolean value.
- The ternary operator ?: can become hard to read when nested, so parentheses are often necessary.
- Optional chaining ?. has its own precedence rules and is commonly combined with nullish coalescing ??.
- Some expressions look similar but behave differently because of unary versus binary operators, such as -x versus x - y.
One especially confusing case is mixing nullish coalescing with logical operators. JavaScript intentionally restricts some combinations unless you use parentheses, because the meaning can be ambiguous.
Problem: This kind of expression can produce a syntax error in modern JavaScript because ?? cannot be mixed with && or || without grouping.
const value = name || fallback ?? "guest";Fix: Add parentheses to make the grouping explicit.
const value = (name || fallback) ?? "guest";The corrected version works because the engine can clearly see how the mixed operators should be grouped.
9. Practical Mini Project
Let's build a small pricing rule example that combines arithmetic, comparison, and logical operators. This shows how precedence helps you compute a result and then decide whether a discount applies.
function calculateTotal(price, quantity, isMember) {
const subtotal = price * quantity;
const discount = isMember && subtotal > 100 ? subtotal * 0.1 : 0;
return subtotal - discount;
}
console.log(calculateTotal(25, 5, true)); // 112.5
console.log(calculateTotal(25, 2, true)); // 50
console.log(calculateTotal(25, 5, false)); // 125This mini project combines the main ideas from the article: multiplication happens before comparison, comparison feeds the ternary operator, and logical AND helps gate the discount by membership status.
10. Key Points
- Operator precedence controls how JavaScript groups an expression before evaluating it.
- Parentheses override precedence and should be used whenever the intended order is not obvious.
- && binds tighter than ||, which often surprises beginners.
- Assignment has low precedence, so be careful not to use = when you mean ===.
- Short, named variables are often clearer than one long expression.
- Some operators have special rules, such as short-circuiting and right-to-left associativity.
11. Practice Exercise
Rewrite the expression below so it is easier to read and its order of evaluation is obvious.
- Task: Create a variable named finalScore.
- Requirement: Start with a base score, add a bonus only if the user is active, and then apply a penalty if the score is above a threshold.
- Expected output: A number that reflects the rules clearly and predictably.
- Hint: Use parentheses and intermediate variables instead of packing everything into one line.
One possible solution is shown below.
const baseScore = 80;
const bonus = true ? 10 : 0;
const afterBonus = baseScore + bonus;
const finalScore = afterBonus > 85 ? afterBonus - 5 : afterBonus;
console.log(finalScore); // 85This solution is not the shortest possible version, but it is much easier to understand and modify.
12. Final Summary
JavaScript operator precedence tells you how expressions are grouped before they are evaluated. Higher-precedence operators run first, equal-precedence operators follow associativity rules, and parentheses can always override the default behavior.
In practice, precedence becomes most important when you combine arithmetic, comparison, logical, and assignment operators in a single expression. Knowing the rules helps you predict results, debug logic errors, and write code that other developers can read without guessing.
When in doubt, prefer parentheses or break the expression into smaller named steps. That approach reduces mistakes and makes your intent far clearer than relying on the reader to remember the precedence table.