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.

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:

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); // 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.

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

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.

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" = 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:

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 36

Fix: Add parentheses if you want the addition first.

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.

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

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)); // 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

11. Practice Exercise

Rewrite the expression below so it is easier to read and its order of evaluation is obvious.

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); // 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.