Menu

JavaScript Operators: Arithmetic, Comparison, Logical, and More

The operators JavaScript gives you for doing math, comparing values, combining booleans, and assigning — with the quirks that actually bite in practice.

Operators Are How Expressions Do Work

Every non-trivial line of JavaScript is built from operators — symbols that take one or two values and produce a new one. + adds, === compares, && combines booleans, ? : picks between two values. Most of them are familiar from other languages; a handful have JavaScript-specific quirks worth knowing up front.

We'll walk through them by category, ending with the ones you'll reach for least but that matter when you need them.

Arithmetic Operators

The basics behave like you'd expect:

index.js
Output
Click Run to see the output here.

A few things worth flagging:

  • / always does floating-point division. 7 / 2 is 3.5, not 3. Use Math.floor(7 / 2) or Math.trunc(7 / 2) if you want an integer.
  • % is the remainder, not true mathematical modulo. It keeps the sign of the left operand: -7 % 3 is -1, not 2.
  • + is overloaded. If either side is a string, it concatenates instead of adding: "3" + 1 is "31". More on that in a moment.

Increment and decrement

index.js
Output
Click Run to see the output here.

The difference between count++ and ++count only matters when you use the expression's value in the same line. As a standalone statement, they do the same thing. Most style guides prefer count += 1 for clarity.

The + Operator Has Two Personalities

This one trips up everyone at least once:

index.js
Output
Click Run to see the output here.

If either operand is a string, + becomes string concatenation and coerces the other side to a string. Every other arithmetic operator goes the opposite way — it coerces strings to numbers:

index.js
Output
Click Run to see the output here.

The takeaway: when you're building strings, prefer template literals (`price: ${5}`). When you're doing math, make sure your inputs are actually numbers — Number(x) or parseInt(x, 10) converts explicitly.

Comparison Operators

Comparisons return booleans. Two flavors: strict and loose.

index.js
Output
Click Run to see the output here.

=== and !== are strict — same value and same type. == and != coerce types before comparing, which leads to surprises like null == undefined being true or [] == false being true. Use === and !== by default. The only common exception is x == null, which is a handy shortcut for "is x either null or undefined?"

The ordering operators work like you'd expect on numbers, and alphabetically on strings:

index.js
Output
Click Run to see the output here.

String comparison is based on character codes, so it's case-sensitive. If you need human-friendly sorting, use String.prototype.localeCompare.

Logical Operators

&& (AND), || (OR), and ! (NOT) combine booleans — but they're more interesting than a pure boolean algebra would suggest.

index.js
Output
Click Run to see the output here.

The twist: && and || don't return true or false. They return one of their operands. && returns the first falsy value, or the last one if all are truthy. || returns the first truthy value, or the last one if all are falsy.

index.js
Output
Click Run to see the output here.

That's why you'll see patterns like const displayName = user.name || "Guest" — pick the first thing that isn't empty. It's concise, but watch out: || treats 0, "", and false as fallback-triggering. If those are legitimate values for you, use ?? instead (below).

Both operators also short-circuit: if the left side already determines the answer, the right side never runs.

index.js
Output
Click Run to see the output here.

The Nullish Coalescing Operator ??

?? is like || but only triggers on null or undefined — not on 0, "", or false.

index.js
Output
Click Run to see the output here.

Use ?? when a legitimate value could be falsy — counts, empty strings, explicit false. Use || when any falsy value should mean "missing." In modern code, ?? is the safer default for optional values with non-null defaults.

Assignment Operators

= assigns. The compound forms combine assignment with another operator:

index.js
Output
Click Run to see the output here.

There are logical assignment operators too — ||=, &&=, and ??= — which assign only if the current value meets a condition:

index.js
Output
Click Run to see the output here.

These are handy for filling in defaults without verbose if statements.

The Ternary Operator

condition ? a : b is an expression version of if/else. It returns a when the condition is truthy, b otherwise:

index.js
Output
Click Run to see the output here.

Ternaries shine for short value-picking. They become hard to read the moment you nest them — if you find yourself writing a ? b : c ? d : e, reach for if/else or a lookup object instead.

typeof and instanceof

typeof returns a string describing the type of its operand:

index.js
Output
Click Run to see the output here.

Two gotchas worth memorizing: typeof null is "object" (a bug from 1995 that's now permanent), and arrays also report "object". Use Array.isArray(x) for arrays and x === null for null.

instanceof checks whether an object was built from a particular constructor:

index.js
Output
Click Run to see the output here.

Spread and Rest Use the Same ...

You'll see ... in two places. As spread, it expands an iterable into individual elements:

index.js
Output
Click Run to see the output here.

As rest, it collects multiple values into a single array — usually in function parameters or destructuring:

index.js
Output
Click Run to see the output here.

Same syntax, opposite jobs. Spread unpacks; rest gathers. Which one is which is determined by context: in a call or literal, it spreads; in a parameter list or destructuring pattern, it collects.

Operator Precedence (When in Doubt, Parenthesize)

Operators have a precedence that decides which one runs first when you mix them. Multiplication beats addition, comparison beats logical, and so on:

index.js
Output
Click Run to see the output here.

The full table is long, and nobody remembers all of it. A simple habit covers 99% of cases: when you mix operators and you're not certain of the order, add parentheses. The code reads better and doesn't depend on the reader's memory.

Bitwise Operators (Rarely What You Want)

For completeness: &, |, ^, ~, <<, >>, and >>> operate on the binary representation of integers. You'll see them in graphics code, low-level protocols, and the occasional flag-bitmask API.

index.js
Output
Click Run to see the output here.

One common-but-questionable trick: n | 0 truncates a number to a 32-bit integer, which people used to abuse as a faster Math.trunc. Don't — Math.trunc is clearer and works for numbers outside the 32-bit range.

Next: if/else

Operators produce values; if/else uses those values to pick a branch of code to run. Most of what you'll do with the comparison and logical operators above is feed their results into conditionals — which is exactly what the next page is about.

Frequently Asked Questions

What are the main operators in JavaScript?

JavaScript has arithmetic (+, -, *, /, %, **), comparison (===, !==, <, >), logical (&&, ||, !), assignment (=, +=, -=), and a few special ones like the ternary ? :, typeof, and nullish coalescing ??. They're the building blocks for expressions and control flow.

What's the difference between == and === in JavaScript?

=== checks that both the value and type match. == coerces types before comparing, so 0 == "0" is true but 0 === "0" is false. Use === by default — the coercion rules of == are subtle enough to cause bugs you won't spot in review.

What does the ternary operator do in JavaScript?

condition ? a : b is a one-line if/else that returns a value. If condition is truthy it evaluates to a, otherwise b. It's useful for short conditional expressions like const label = count === 1 ? 'item' : 'items', but nesting ternaries gets hard to read fast.

When should I use ?? instead of ||?

|| falls back on any falsy value, including 0, "", and false. ?? only falls back on null or undefined. If you want count ?? 10 to keep a legitimate 0, use ??. If you genuinely want any falsy value to trigger the fallback, stick with ||.

Learn to code with Coddy

GET STARTED