JavaScript Operators: Null Coerced to 0 by == Causes Outage
Null userBalance with == 0 returns true, bypassing payment.
- Operators are symbols that perform operations on values: arithmetic, assignment, comparison, logical, and more
- Use === (strict equality) instead of == to avoid type coercion bugs
- Compound assignment operators (+=, -=) update a variable in-place, cleaner than repeating the variable name
- Nullish coalescing (??) only falls back for null/undefined, unlike || which catches all falsy values
- The modulus (%) operator gives remainder — useful for even/odd checks and cyclic indexing
- Optional chaining (?.) safely accesses nested properties without crashing on null or undefined
Think of operators as the verbs of JavaScript — they're the action words that tell your code what to DO with values. Just like a calculator uses +, -, × and ÷ to work with numbers, JavaScript uses operators to add values, compare them, combine conditions, and make decisions. If variables are the boxes that hold your data, operators are the tools you use to work with what's inside those boxes.
Every single JavaScript program that has ever been written — from a simple age checker to a full e-commerce platform — relies on operators. They're the invisible machinery behind every calculation, every if/else decision, every loop condition, and every value assignment. Without operators, your code would just be a pile of data with nothing happening to it. They are, quite literally, how JavaScript thinks.
Before operators existed in programming languages, doing anything useful with data was painfully complex. Operators solve a fundamental problem: how do you tell a computer to compare two values, combine them, or use one to modify another? Operators give you a clean, readable shorthand for all of that. Instead of writing a paragraph of instructions to add two numbers, you just write a + b.
By the end of this article, you'll know every major category of JavaScript operator, understand exactly when and why to use each one, spot the classic mistakes that trip up beginners (and even some experienced devs), and be able to confidently answer operator-related questions in a JavaScript interview. Let's build this up piece by piece.
Arithmetic Operators — Making JavaScript Do the Math
Arithmetic operators are the most intuitive place to start because you already know them from school. They perform mathematical operations on numbers. JavaScript gives you the standard four — addition (+), subtraction (-), multiplication (), and division (/) — plus two more that often surprise beginners: modulus (%) and exponentiation (*).
The modulus operator is the one people forget exists. It gives you the remainder after division, not the result of division. So 10 % 3 gives you 1, because 3 goes into 10 three times with 1 left over. This is incredibly useful for things like figuring out if a number is odd or even, or cycling through items in a list.
Exponentiation () is the power operator. 2 8 means '2 to the power of 8', which is 256. You'll use this whenever you need to calculate areas, compound interest, or work with any kind of exponential growth.
JavaScript also has the ++ (increment) and -- (decrement) operators which add or subtract exactly 1 from a value. They look small but they're everywhere — especially inside loops.
Beware: JavaScript's floating-point arithmetic can produce unexpected results. 0.1 + 0.2 is 0.30000000000000004, not 0.3. This isn't a JavaScript bug — it's how IEEE 754 floating-point works in every language. For financial calculations, always use integers (cents) or a dedicated decimal library.
Assignment Operators — Storing and Updating Values Efficiently
You already know the basic assignment operator: =. It takes the value on the right and stores it in the variable on the left. But JavaScript has a whole family of compound assignment operators that combine assignment with arithmetic in one step, and they'll make your code much cleaner once you know them.
Compound assignment operators like +=, -=, *=, /=, and %= are shortcuts. Instead of writing score = score + 10, you write score += 10. It means exactly the same thing but it's shorter, less repetitive, and reads more naturally. Senior developers use these constantly.
Think of it like this: if you have a savings account with £200 in it and you deposit £50, you don't empty the account and refill it with £250. You just add £50 to what's already there. Compound assignment operators work the same way — they modify what's already in the variable rather than replacing it from scratch.
There's also the nullish assignment operator (??=) which only assigns a value if the variable is currently null or undefined. It's a newer addition but incredibly useful for setting default values safely.
A subtle danger: using assignment operators inside conditions (e.g., if (score = 10)) is a classic bug. The single = always assigns, not compares. Linters catch this — but they only work if you run them. Always prefer deliberate assignment before the condition.
if (response = data) instead of if (response === data) in a middleware.no-cond-assign rule and never put assignment inside an if statement.Comparison Operators — How JavaScript Makes Decisions
Comparison operators are the foundation of every decision your code makes. They compare two values and always return either true or false. This true/false result is what powers every if statement, every loop condition, and every ternary expression.
JavaScript has two equality operators and that trips everyone up: == (loose equality) and === (strict equality). The difference is huge. Loose equality (==) attempts to convert both values to the same type before comparing — so '5' == 5 is true because JavaScript quietly converts the string '5' into the number 5. Strict equality (===) compares both the value AND the type — so '5' === 5 is false because one is a string and one is a number.
For almost all situations, you should use === (strict equality). It does exactly what you think it does with no surprise type conversions happening behind the scenes. The == operator's type coercion behaviour is a notorious source of bugs.
The same logic applies to inequality: != (loose) vs !== (strict). Always prefer !== in your code.
Beyond equality, you have >, <, >=, <=. These work across strings too — JavaScript compares strings lexicographically by Unicode code point. That means '2' > '10' is true because '2' has a higher code point than '1'. Be careful comparing strings that represent numbers. Always convert to number first: Number('2') > Number('10').
x === null || x === undefined.0 == false is true. Use === or convert to boolean explicitly.Logical Operators — Combining Conditions Like a Pro
Logical operators let you combine multiple conditions into one expression. Instead of nesting a dozen if statements inside each other, you can chain conditions together cleanly on a single line. There are three core logical operators: && (AND), || (OR), and ! (NOT).
Think of && like a bouncer at a club with two rules: 'You must be over 18 AND have ID.' Both conditions must be true for you to get in. If either one fails, you're not getting through. That's &&.
The || operator is more lenient: 'You can enter if you have a VIP pass OR a regular ticket.' Just one condition needs to be true. That's ||.
The ! operator simply flips a boolean: !true is false and !false is true. It's useful for toggling states, like switching a dark mode setting on and off.
JavaScript also has two powerful modern operators: ?? (nullish coalescing) which returns the right side only if the left is null or undefined, and the optional chaining operator ?. which safely accesses properties without crashing when something is null. These two are modern essentials.
A critical nuance: && and || evaluate to one of their operands, not strictly to true or false. This is called short-circuit evaluation. For example, 0 && true evaluates to 0 (not false), and 'hello' || false evaluates to 'hello' (not true). This behavior is often used for conditional rendering or fallbacks — but it can trip you up when you expect a boolean.
|| to default empty input to '0' — but when user entered 0 intentionally, it was overridden.0 || '0' evaluates to '0' because 0 is falsy.Ternary and Conditional Operators — Compact Decision Making
The ternary operator (? :) is a concise way to write an if-else statement on a single line. Its syntax is: condition ? exprIfTrue : exprIfFalse. It returns one of two values based on the truthiness of the condition.
It's not just a shorthand — it's an expression, meaning it can be used directly in assignments, return statements, or even inside other expressions. This makes it incredibly powerful for short conditional logic.
However, misuse is common. Nesting ternaries (ternary inside ternary) quickly becomes unreadable. A general rule: if the logic fits on one line and is obvious, use a ternary. If you start thinking 'else if', use a regular if-else or a switch statement instead.
The ternary operator is also a common source of bugs when developers forget that ? : returns a value and accidentally use assignment (=) inside one of the branches. Also, operator precedence can trip you up — wrap the ternary in parentheses if combined with other operators.
'Price: ' + (isDiscounted ? 10 : 20) not 'Price: ' + isDiscounted ? 10 : 20 — the latter concatenates the string with the condition before the ternary evaluates.return userId ? fetchUser(userId) : null without realizing ? has lower precedence than ? : in some contexts.The Comma Operator and Other Odd Operators — Using the Less Common Ones
JavaScript has a few lesser-known operators that you won't use every day, but when you need them, they're indispensable. The comma operator (,) evaluates both operands and returns the second one. It's often used in for loops: for (let i = 0, j = 10; i < j; i++, j--). Outside loops, it can make code cryptic — use sparingly.
The delete operator removes a property from an object. It returns true if successful, false otherwise (it doesn't free memory directly). delete only works on object properties, not on variables or array elements (it leaves a hole).
The typeof operator returns a string indicating the type of an operand. Common traps: typeof null returns 'object' (a long-standing bug), and typeof array returns 'object' too. Use Array.isArray() to check arrays.
The instanceof operator checks whether an object is an instance of a specific constructor. It works across prototype chains, but fails across different execution contexts (e.g., iframes).
The grouping operator ( ) simply controls precedence in expressions. Use it liberally to make your intent clear.
- typeof returns a primitive type string — works on any value.
- instanceof checks the prototype chain — only works on objects.
- typeof null === 'object' is a historical bug; check for null explicitly.
- instanceof fails across realms (e.g., iframes, different Node contexts) — use
Object.prototype.toString.call()for robustness.
typeof [] returned 'object', and the code assumed it was a plain object.for...in instead of for...of.Array.isArray() to distinguish arrays from plain objects.Array.isArray() not typeof for array checks.Production Outage: Loose Equality Killed Our Billing Pipeline
if (userBalance == 0) was used to check if a user had a zero balance. When userBalance was null (no transactions yet), JavaScript coerced null to 0, making the condition true. The payment step was skipped for all new users.== to === and added an explicit null check: if (userBalance === 0 || userBalance === null) – but the real fix was to use === and handle null/undefined separately.- Always use === (strict equality) unless you have an explicit, documented reason for type coercion.
- Linters (ESLint's eqeqeq rule) catch this automatically — enforce it in CI.
- When dealing with numeric values that could be null or undefined, check for those explicitly before the equality comparison.
if (x = 10) assigns 10 to x, which is truthy. Use if (x === 10) and turn on ESLint's no-cond-assign rule.|| instead of ??. ?? only triggers for null/undefined, not for 0, '', or false. Switch to nullish coalescing if those are valid inputs.?.) to safely access deeply nested properties. Replace obj.a.b with obj?.a?.b to return undefined instead of crashing.Math.abs(a - b) < 0.0001 instead of a === b. For currency, consider using integer cents or a library like decimal.js.== with === except when you explicitly need type coercion (rare).Key takeaways
Array.isArray() to check for arrays, not typeof.Common mistakes to avoid
5 patternsUsing = instead of === inside an if condition
=) returns the assigned value, which is truthy unless it's 0, null, undefined, false, or empty string. The bug silently assigns the value instead of comparing.no-cond-assign (especially except-parens) to catch this. Example: if (userScore === 100) instead of if (userScore = 100).Using == instead of === and getting surprised by type coercion
userInput == 0 return true when userInput is '0' (string), false, null, or even an empty array — because == coerces types in complex ways. This leads to logic bugs that are difficult to trace.eqeqeq with 'always' option. Example: if (userInput === 0) will only match number 0, not string '0' or null.Using || for default values when 0 or false are valid inputs
const quantity = input || 10 sets quantity to 10 because 0 is falsy. The bug is silent — data is overwritten without error.?? instead: const quantity = input ?? 10. This only falls back to 10 when input is null or undefined, preserving 0, false, and empty string as valid values.Confusing logical && and || with boolean return
0 || true to return false (because 0 is falsy), but it returns true (the second operand). Expecting true && 'hello' to return true, but it returns 'hello'. This can cause subtle bugs when using these operators in non-boolean contexts like JSX.!! (double NOT) to coerce: !!(0 || true) returns true. Or better, explicitly write conditions that return booleans.Forgetting that `typeof null === 'object'` is a bug
if (typeof value === 'object' && value !== null) is common, but many developers forget the null check. When value is null, the condition passes and later code crashes trying to access properties on null.if (value !== null && typeof value === 'object'). Or use value && typeof value === 'object' if null/falsy values should be excluded.Interview Questions on This Topic
What is the difference between == and === in JavaScript, and which one should you use in production code and why?
x == null is true for both null and undefined. But even then, many teams prefer explicit checks: x === null || x === undefined. Linters typically enforce === by default.Frequently Asked Questions
That's JS Basics. Mark it forged?
7 min read · try the examples if you haven't