Key Takeaways
- JavaScript operators act on operands to calculate results, compare values, choose alternatives, and update state.
- Prefer strict equality,
===and!==, unless you intentionally want type conversion. &&and||return operand values. Use??for defaults that preserve0,false, and empty strings.- Parentheses make grouping explicit; bitwise operators require particular care because Number operands undergo 32-bit integer conversion.
JavaScript operators perform operations on values called operands. An expression combines values and operators to produce a result: in 2 + 2, + adds two operands and produces 4.
console.log(2 + 2); // 4Despite the ES6 title, this reference covers both long-standing operators and later additions, including exponentiation, optional chaining, nullish coalescing, and logical assignment. Run each code block independently in a modern browser console or a supported Node.js runtime.
Types of JavaScript Operators
The main families are arithmetic, relational and equality, logical, assignment, bitwise, and conditional operators. Unary operators take one operand, binary operators take two, and the conditional operator takes three; these descriptions count operands rather than describe what an operator does.
The MDN operator reference also covers keyword operators such as typeof, delete, and void. Operators aren't limited to punctuation.
JavaScript Arithmetic Operators
Addition, subtraction, multiplication, and division
console.log(2 + 2); // 4: addition
console.log(4 - 2); // 2: subtraction
console.log(5 * 5); // 25: multiplication
console.log(4 / 2); // 2: division
console.log(5 / 2); // 2.5: Number division preserves the fractionRemainder and exponentiation
% is the remainder operator, not mathematical modulo: a nonzero result has the dividend's sign. The exponentiation operator, **, raises a base to a power; ^ means bitwise XOR, not exponentiation.
console.log(6 % 5); // 1
console.log(-6 % 5); // -1
console.log(2 ** 3); // 8Increment and decrement
++ adds one; -- subtracts one. Postfix forms return the old value, while prefix forms return the updated value.
let a = 2;
a++;
console.log(a); // 3
let b = 2;
b--;
console.log(b); // 1
let count = 2;
console.log(count++); // 2; count becomes 3
console.log(++count); // 4; count becomes 4Numeric addition versus string concatenation
Coercion means automatic type conversion. The addition operator first converts operands to primitive values; if either is a string, it concatenates strings instead of adding numbers.
console.log("5" + 2); // "52"
console.log("5" - 2); // 3
console.log(Number("5") + 2); // 7
console.log(+"5"); // 5: unary plus
console.log(-5); // -5: unary negationConvert external input deliberately before doing arithmetic. Don't rely on subtraction to fix an unexpected string.
JavaScript Comparison Operators
Relational comparisons
<, >, <=, and >= compare ordering and return booleans. With two strings, ordering is lexicographic by UTF-16 code units; a string compared with a Number undergoes numeric conversion.
console.log(2 > 1); // true
console.log(2 < 1); // false
console.log(2 >= 2); // true
console.log(1 <= 2); // true
console.log("2" < "10"); // false: string ordering
console.log("2" < 10); // true: numeric comparisonEquality: == versus ===
Use === and !== by default: they compare without converting operand types. == and != allow coercion under JavaScript's equality rules.
console.log(6 == 5); // false
console.log(2 != 3); // true
console.log(0 == false); // true: false converts to 0
console.log(0 === false); // false: different types
console.log("5" == 5); // true
console.log("5" === 5); // false
console.log("5" !== 5); // true
console.log({} === {}); // false: different objects
console.log(NaN === NaN); // falseStrict equality doesn't compare object contents: objects must be the same reference. One intentional use of coercive equality is value == null to accept both null and undefined; use two explicit strict checks if that better fits your team's conventions.
JavaScript Logical Operators and Short-Circuiting
AND, OR, and NOT
Logical AND, &&, returns its left operand when that value is falsy; otherwise, it returns its right operand. || returns its left operand when truthy, otherwise its right operand. Both skip the right-hand expression when the left determines the result: this is short-circuit evaluation.
Falsy values include false, 0, 0n, "", null, undefined, and NaN. Empty arrays and objects are truthy. Unlike AND and OR, ! always produces a boolean.
console.log(true && false); // false
console.log(true || false); // true
console.log(!true); // false
console.log("ready" && 42); // 42
console.log("" || "Guest"); // "Guest"
let calls = 0;
function fallback() {
calls++;
return "computed";
}
console.log("saved" || fallback()); // "saved"
console.log(0 && fallback()); // 0
console.log(calls); // 0: neither call ranNullish coalescing: ?? versus ||
Nullish coalescing, ??, evaluates and returns the fallback only when its left operand is null or undefined. Use it when zero, false, or an empty string is a valid value.
| value | value || "fallback" | value ?? "fallback" |
|---|---|---|
0 | "fallback" | 0 |
false | "fallback" | false |
"" | "fallback" | "" |
NaN | "fallback" | NaN |
null | "fallback" | "fallback" |
undefined | "fallback" | "fallback" |
JavaScript requires parentheses when you mix ?? directly with || or &&.
console.log((null ?? "") || "Guest"); // "Guest"
// null ?? "" || "Guest"; // Invalid syntax without groupingOptional Chaining: ?.
Optional chaining stops a property access or call when the value before ?. is nullish, returning undefined. Place it at each level that may be absent.
const user = { profile: null };
console.log(user.profile?.name ?? "Guest"); // "Guest"
const handlers = {};
console.log(handlers.onSave?.()); // undefined
const items = null;
console.log(items?.[0]); // undefinedJavaScript Assignment Operators
Simple and compound assignments
= assigns a value; arithmetic and bitwise compound assignments combine an operation with an update. The complete family appears in the MDN expressions and operators guide.
- Arithmetic:
+=,-=,*=,/=,%=,**=. - Bitwise:
&=,|=,^=,<<=,>>=,>>>=. - Logical:
&&=,||=,??=.
let x = 2;
console.log(x); // 2
let added = 2;
added += 1;
console.log(added); // 3
let subtracted = 2;
subtracted -= 1;
console.log(subtracted); // 1
let multiplied = 2;
multiplied *= 2;
console.log(multiplied); // 4
let divided = 2;
divided /= 2;
console.log(divided); // 1
let remainder = 6;
remainder %= 5;
console.log(remainder); // 1
let power = 2;
power **= 3;
console.log(power); // 8For a simple variable, x += y has the effect of x = x + y, including string concatenation. Compound assignments evaluate their left-hand reference only once. For declaration and reassignment rules, see JavaScript variable declarations.
Logical assignment
&&= assigns only when the current value is truthy; ||= assigns when falsy; ??= assigns when nullish. Otherwise, they skip both the right-hand expression and the assignment.
const settings = { retries: 0, label: "", enabled: true };
settings.retries ??= 3; // Keeps 0
settings.label ||= "Guest"; // Replaces the empty string
settings.enabled &&= false; // Replaces the truthy value
console.log(settings.retries); // 0
console.log(settings.label); // "Guest"
console.log(settings.enabled); // falseJavaScript Bitwise Operators
Use bitwise operators for explicit bit manipulation, such as packed flags—not as a general speed trick. With Number operands, bitwise operations use 32-bit integers, discarding fractional parts and bits beyond that width.
AND, OR, XOR, and NOT
& sets a result bit when both input bits are 1; | sets it when either is 1; ^ sets it when the bits differ; ~ inverts every bit.
Shown using only the lowest four bits:
0101 (5)
& 0011 (3)
------
0001 (1)const a = 0b0101;
const b = 0b0011;
console.log(a & b); // 1
console.log(a | b); // 7
console.log(a ^ b); // 6
console.log(~a); // -6: all 32 bits are invertedLeft shift <<, signed right shift >>, and zero-fill right shift >>>
<< shifts left and inserts zeros on the right. >> shifts right while preserving the sign; >>> fills the left with zeros and returns an unsigned 32-bit result.
console.log(5 << 1); // 10
console.log(-8 >> 1); // -4
console.log(-8 >>> 1); // 2147483644
console.log((2 ** 32) | 0); // 0: higher bits are lostThe large difference between the two right-shift results is intentional. For more worked examples, see JavaScript bitwise operators.
BigInt Operators
BigInt represents integers without Number's fixed precision. Numeric arithmetic cannot mix BigInt and Number operands without explicit conversion, and BigInt division truncates toward zero.
console.log(2n + 3n); // 5n
console.log(7n / 2n); // 3n
console.log(2n + BigInt(1)); // 3n
console.log(2n < 3); // true: comparison permits mixed types
console.log(2n === 2); // false: types differ
try {
console.log(2n + 1);
} catch (error) {
console.log(error.name); // "TypeError"
}BigInt supports &, |, ^, ~, <<, and >> without Number's 32-bit truncation. It doesn't support >>> or unary +. Converting a large BigInt to Number can lose precision.
The Ternary Operator
The conditional operator, condition ? whenTrue : whenFalse, is an expression that produces a value. Only the selected branch is evaluated.
console.log(true ? 2 : 3); // 2
const isMember = true;
const price = isMember ? 10 : 15;
console.log(price); // 10Use a ternary when choosing between two readable alternatives. Prefer if...else control flow for multiple actions or complicated branches; deeply nested ternaries are rarely worth the saved lines.
typeof and Its Surprises
typeof returns a type-label string, not a complete description of a value.
console.log(typeof 3); // "number"
console.log(typeof (() => {})); // "function"
console.log(typeof null); // "object": a historical quirk
console.log(typeof []); // "object"
console.log(typeof 2n); // "bigint"
// This identifier is intentionally undeclared.
console.log(typeof stackchiefMissingValue); // "undefined"Reading an undeclared identifier normally throws a ReferenceError, but typeof returns "undefined". That exception doesn't apply to a let or const binding before initialization in its scope—the period called the temporal dead zone. See JavaScript arrays for collection-specific operations rather than relying on typeof to identify arrays.
Other Keyword Operators: in, instanceof, delete, and void
intests whether an object has a property, including inherited properties. UseObject.hasOwn(object, key)when you need only its own properties.instanceof, by default, checks whether a constructor's prototype occurs in an object's prototype chain; it isn't a structural comparison of object fields.deleteremoves configurable own properties, not lexical variable bindings. Deleting an array element leaves a hole rather than shrinking its length.voidevaluates an expression and producesundefined.
const record = { name: "Ada" };
console.log("name" in record); // true
console.log("toString" in record); // true: inherited
console.log(record instanceof Object); // true
console.log(delete record.name); // true
console.log("name" in record); // false
console.log(void (2 + 2)); // undefinedtypeof, delete, and void are unary operators written as keywords. By contrast, ... is spread or rest syntax, not a general-purpose unary operator.
JavaScript Operator Precedence and Associativity
Precedence determines how operators group; associativity resolves grouping among operators at the same precedence level. Parentheses let you make that grouping explicit.
console.log(2 + 3 * 4); // 14: 2 + (3 * 4)
console.log((2 + 3) * 4); // 20
console.log(10 - 3 - 2); // 5: (10 - 3) - 2
console.log(2 ** 3 ** 2); // 512: 2 ** (3 ** 2)
console.log(-(2 ** 2)); // -4
// -2 ** 2; // Invalid syntax: parenthesize the intended groupingThis abbreviated table runs from higher to lower precedence. The conditional and assignment rows need a caveat: the conditional operator grammar accepts an AssignmentExpression in either branch, so assignments there don't require parentheses.
| Operators | Grouping |
|---|---|
(expression) | Explicit grouping |
** | Right-to-left |
* / % | Left-to-right |
+ - | Left-to-right |
<< >> >>> | Left-to-right |
< <= > >= in instanceof | Left-to-right |
== != === !== | Left-to-right |
& | Left-to-right |
^ | Left-to-right |
| | Left-to-right |
&& | Left-to-right |
||, ?? | Left-to-right; mixing requires parentheses |
condition ? a : b | Right-to-left |
| Assignment operators | Right-to-left |
Grouping isn't the same as operand evaluation order: operands are evaluated left-to-right, subject to short-circuiting. Don't use associativity to predict which function call runs first.
Common Mistakes
- Using
||for every default. Choose??when falsy values are meaningful. - Confusing logical and bitwise operators.
&and|perform bit operations and don't provide logical short-circuiting. - Using bitwise conversion as a general optimization.
value | 0can discard information. Reach for it only when you actually need signed 32-bit conversion. - Compressing too much into an expression. Name intermediate values and use parentheses or statements when that makes the decision easier to review.
FAQ
What is the difference between == and === in JavaScript?
== allows type conversion before comparison; === does not. Prefer === by default: 0 == false is true, while 0 === false is false.
What is the difference between || and ?? in JavaScript?
|| uses its fallback for any falsy left operand, while ?? uses it only for null or undefined. Use ?? when 0, false, or an empty string should remain valid values.
How does operator precedence work in JavaScript?
Higher-precedence operators group more tightly, so multiplication groups before addition. Associativity resolves grouping at equal precedence, and parentheses make your intended grouping explicit.
What does the >>> operator do in JavaScript?
The zero-fill right-shift operator shifts a Number's 32-bit representation right, inserts zeros on the left, and returns an unsigned result. Unlike signed right shift, it doesn't preserve a negative sign, and it doesn't support BigInt.
When should I use the ternary operator instead of if...else?
Use a ternary to choose one value from two simple alternatives, such as a label or price. Use if...else when branches contain multiple actions or nesting makes the expression difficult to read.
Further Reading
- MDN: Expressions and operators — the broad guide and complete assignment family.
- MDN: Operator precedence — the full table and evaluation-order caveats.
- MDN: Equality comparisons and sameness — coercion, identity, and equality edge cases.
- MDN: Nullish coalescing — defaulting without replacing valid falsy values.
- MDN: Optional chaining — property access, optional calls, and limitations.
- MDN: BigInt — arithmetic, conversions, and supported operators.
- MDN: typeof — return values and undeclared-variable behavior.
- MDN: Unsigned right shift — zero filling and unsigned Number results.
