Operators & Expressions
Operators and expressions are the fundamental building blocks of JavaScript logic. If variables are the "nouns" of your code, operators are the "verbs" that act upon them. An expression is any valid unit of code that resolves to a single value.
This chapter provides a deep dive into how JavaScript manipulates data, makes comparisons, and evaluates complex logic.
Why This Topic Matters
Operators and expressions appear in every single line of meaningful code, from simple math to complex business logic. Understanding them deeply will:
- Prevent Coercion Bugs: Knowing when
5 + "5"becomes"55"and when it doesn't. - Improve Readability: Mastering short-circuit logic and ternary operators makes code cleaner.
- Boost Debugging Speed: Understanding operator precedence helps you spot logic errors faster.
- Modernize Your Code: Utilizing optional chaining and nullish coalescing prevents "cannot read property of undefined" crashes.
How To Study This Chapter
- Read the Concept: Understand the "why" before the "how".
- Examine the Examples: Look at the input and predict the output.
- Experiment: Open your browser console (F12) and try the edge cases mentioned.
- Visualize: Use the diagrams to build a mental model of how data flows through expressions.
Arithmetic Operators
Arithmetic operators perform standard mathematical calculations.
| Operator | Name | Description | Example |
|---|---|---|---|
+ | Addition | Adds values or concatenates strings | 10 + 5 (15) |
- | Subtraction | Subtracts the right from the left | 10 - 5 (5) |
* | Multiplication | Multiplies values | 10 * 5 (50) |
/ | Division | Divides the left by the right | 10 / 5 (2) |
% | Remainder (Modulo) | Returns the integer remainder of division | 10 % 3 (1) |
** | Exponentiation | Raises the left to the power of the right | 2 ** 3 (8) |
Under the Hood: The Floating Point Problem
JavaScript uses the IEEE 754 standard for numbers, which represents all numbers as 64-bit floats. This leads to a famous "quirk":
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
Lesson: Never compare floating-point numbers directly for equality. Instead, check if the difference is smaller than a tiny value (called Number.EPSILON).
Assignment Operators
Assignment operators assign a value to the left-hand operand based on the value of the right-hand operand.
The Basic Assignment
let x = 10; — The value 10 is stored in the memory location labeled x.
Compound Assignments
These are shortcuts for performing an operation and then assigning the result back to the variable.
let score = 50;
score += 10; // Same as: score = score + 10; (Result: 60)
score -= 5; // Same as: score = score - 5; (Result: 55)
score *= 2; // Same as: score = score * 2; (Result: 110)
score /= 10; // Same as: score = score / 10; (Result: 11)
Note: The assignment operation itself is an expression that returns the assigned value. This allows for patterns like a = b = c = 5;.
Comparison & Relational Operators
Comparison operators return a boolean value (true or false).
Strict vs. Abstract Equality
This is a critical distinction in JavaScript.
- Strict Equality (
===): Returnstrueonly if both the value and the type are identical. - Abstract Equality (
==): Attempts to convert the types (coercion) before comparing values.
Relational Operators
These test the relationship between values or properties.
in: Checks if a property exists in an object.const user = { name: "Alice" }; console.log("name" in user); // trueinstanceof: Checks if an object is an instance of a specific class/constructor.const now = new Date(); console.log(now instanceof Date); // true
Logical Operators & Coercion
Logical operators are used to determine the logic between variables or values.
Truthy vs. Falsy
In JavaScript, every value is inherently "truthy" or "falsy" when evaluated in a boolean context.
The 6 Falsy Values:
false0(and-0,0n)""(empty string)nullundefinedNaN
Everything else is truthy, including [], {}, and "0".
Short-Circuit Evaluation
Logical operators return the value that decided the outcome.
- AND (
&&): Returns the first falsy value, or the last value if all are truthy. - OR (
||): Returns the first truthy value, or the last value if all are falsy.
const name = "Alice";
const greeting = name && `Hello, ${name}`; // "Hello, Alice"
const defaultUser = "" || "Guest"; // "Guest"
Modern Operators: Nullish & Optional Chaining
Modern JavaScript (ES2020+) introduced operators to solve common "value missing" problems safely.
Nullish Coalescing (??)
Unlike ||, ?? only triggers on null or undefined. This is safer for numbers (0) or empty strings.
let count = 0;
let result1 = count || 10; // 10 (because 0 is falsy)
let result2 = count ?? 10; // 0 (because 0 is NOT null/undefined)
Optional Chaining (?.)
Safely access deep properties. Returns undefined if any link in the chain is nullish.
const user = { profile: { name: "Bob" } };
const zip = user?.address?.zip; // undefined (no crash!)
Advanced & Utility Operators
Bitwise Operators
Act on the 32-bit binary representation of numbers.
&(AND),|(OR),^(XOR),~(NOT).<<(Left Shift),>>(Right Shift).
Utility Operators
delete: Removes a property from an object.void: Evaluates an expression and returnsundefined.- Comma (
,): Evaluates multiple expressions and returns the last one.let x = (1, 2, 3); // x is 3
The Ternary Operator
The only JavaScript operator that takes three operands.
Syntax: condition ? exprIfTrue : exprIfFalse
const status = age >= 18 ? "Adult" : "Minor";
Unary Operators
typeof: Returns a string of the value type.!(NOT): Negates truthiness.!!converts any value to a boolean.+(Unary Plus): Coerces values to numbers.++/--: Increment/Decrement (Prefix vs Postfix).
Operator Precedence & Associativity
| Priority | Operator | Description | Associativity |
|---|---|---|---|
| 1 | ( ) | Grouping | n/a |
| 2 | . / ?. / [] / () | Property / Call | Left-to-Right |
| 3 | ++ / -- / ! / typeof / void / delete | Unary | Right-to-Left |
| 4 | ** | Exponentiation | Right-to-Left |
| 5 | * / / / % | Multiplicative | Left-to-Right |
| 6 | + / - | Additive | Left-to-Right |
| 7 | << / >> | Bitwise Shift | Left-to-Right |
| 8 | < / <= / > / >= / in / instanceof | Relational | Left-to-Right |
| 9 | === / !== / == / != | Equality | Left-to-Right |
| 10 | && | Logical AND | Left-to-Right |
| 11 | ` | /??` | |
| 12 | ? : | Ternary | Right-to-Left |
| 13 | = / += | Assignment | Right-to-Left |
| 14 | , | Comma | Left-to-Right |
Common Mistakes & Pitfalls
- Assignment in a Condition:
if (x = 5)assigns instead of compares. - String Concatenation:
1 + 2 + "3"is"33". - NaN Comparison:
NaN === NaNisfalse. UseNumber.isNaN().
Mini Exercises
- The Mystery Result: Predict the result of
10 + 5 * 2 / (4 - 2). - Short-Circuit Challenge: What does
"Orange" && 0 || "Apple"return? Why? - Safety First: Refactor
user && user.address && user.address.zipusing optional chaining. - Ternary Toggle: Write a ternary that returns "Light Mode" if
isDarkis false, and "Dark Mode" if it's true. - Coercion Trap: Explain why
[] == ![]istrue. Hint:![]isfalse.[] == falsetriggers coercion. Both become0.
Review Questions
- Why should you avoid using
==for comparing numbers and strings? - What is the difference between
null || "default"andnull ?? "default"? - How does
x++differ from++xin aconsole.logstatement? - What are the six purely "falsy" values in JavaScript?
- In
a || b && c, which part evaluates first?
Reference Checklist
- I understand why
0.1 + 0.2is not0.3. - I can explain the difference between
==and===. - I know how to use
??for defaults without blocking0. - I can use
?.for safe navigation. - I understand short-circuiting for
&&and||. - I know how to use parentheses to override precedence.