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

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.

JavaScript
const result1 = 2 + 3 * 4;
const result2 = (2 + 3) * 4;

console.log(result1); // 14
console.log(result2); // 20
Output✓ Tested · Node 24
14
20

In 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.

JavaScript
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.

JavaScript
const total = 10 + 6 / 2;
// 10 + 3 = 13

Because 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.

JavaScript
const isValid = 4 + 2 > 5;
// (4 + 2) > 5 = true

This 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.

JavaScript
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.

JavaScript
const flag = !true && false;
// Grouped as: (!true) && false = false

const kind = typeof "hello" === "string";
// Grouped as: (typeof "hello") === "string" = true

Here, 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.

JavaScript
const value = 10 + 2 * 3;
// 16, not 36

Fix: Add parentheses if you want the addition first.

JavaScript
const value = (10 + 2) * 3;
// 36

The 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.

JavaScript
const allowed = isMember || hasTicket && isOpen;

Fix: Make the intended grouping obvious with parentheses.

JavaScript
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.

JavaScript
let count = 3;

if (count = 0) {
  console.log("empty");
}

Fix: Use strict equality when you want a comparison.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
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.

JavaScript
const value = name || fallback ?? "guest";

Fix: Add parentheses to make the grouping explicit.

JavaScript
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.

JavaScript
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)); // 125
Output✓ Tested · Node 24
112.5
50
125

This 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.

Show solution
JavaScript
const baseScore = 80;
const bonus = true ? 10 : 0;
const afterBonus = baseScore + bonus;
const finalScore = afterBonus > 85 ? afterBonus - 5 : afterBonus;

console.log(finalScore); // 85
Output✓ Tested · Node 24
85

This 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.