JavaScript Operators
Operators allow you to perform operations on variables and values. JavaScript provides arithmetic, comparison, logical, assignment, and many other operators.
🔢 Arithmetic Operators
// Basic arithmetic
let a = 10;
let b = 3;
console.log(a + b); // 13 (Addition)
console.log(a - b); // 7 (Subtraction)
console.log(a * b); // 30 (Multiplication)
console.log(a / b); // 3.3333... (Division)
console.log(a % b); // 1 (Modulus - remainder)
console.log(a ** b); // 1000 (Exponentiation - ES2016)
// Increment and decrement
let x = 5;
x++; // Post-increment: x = 6
++x; // Pre-increment: x = 7
x--; // Post-decrement: x = 6
--x; // Pre-decrement: x = 5
// Difference between pre and post
let y = 5;
console.log(y++); // 5 (returns then increments)
console.log(y); // 6
let z = 5;
console.log(++z); // 6 (increments then returns)
console.log(z); // 6
// Unary operators
console.log(+true); // 1 (converts to number)
console.log(+'5'); // 5
console.log(-'5'); // -5
console.log(+'hello'); // NaN
➕ Assignment Operators
// Basic assignment
let x = 10;
// Compound assignment
x += 5; // x = x + 5 → 15
x -= 3; // x = x - 3 → 12
x *= 2; // x = x * 2 → 24
x /= 4; // x = x / 4 → 6
x %= 4; // x = x % 4 → 2
x **= 3; // x = x ** 3 → 8
// Logical assignment (ES2021)
let a;
a ||= 10; // a = a || 10 (if falsy, assign 10)
console.log(a); // 10
let b = 0;
b ||= 5; // b becomes 5 (0 is falsy)
let c = null;
c ??= 10; // c = c ?? 10 (if null/undefined, assign 10)
console.log(c); // 10
let d = false;
d &&= true; // d = d && true (if truthy, assign true)
console.log(d); // false (d was falsy)
⚖️ Comparison Operators
// Equality
console.log(5 == 5); // true (loose equality)
console.log(5 == '5'); // true (converts types)
console.log(5 === 5); // true (strict equality)
console.log(5 === '5'); // false (different types)
console.log(5 != '6'); // true (loose inequality)
console.log(5 !== '5'); // true (strict inequality)
// Relational
console.log(10 > 5); // true
console.log(10 < 5); // false
console.log(10 >= 10); // true
console.log(5 <= 10); // true
// String comparison (lexicographical)
console.log('apple' < 'banana'); // true
console.log('Z' < 'a'); // true (uppercase < lowercase)
console.log('10' < '2'); // true (string comparison!)
console.log('10' < 2); // false (converts to number)
// Comparing different types
console.log('5' > 3); // true (converts '5' to 5)
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(NaN === NaN); // false (NaN is not equal to anything!)
console.log(Object.is(NaN, NaN)); // true (ES6 method)
🔗 Logical Operators
AND (&&)
// Returns first falsy value or last value
console.log(true && true); // true
console.log(true && false); // false
console.log(false && true); // false
// Short-circuit evaluation
console.log(5 && 10); // 10 (both truthy, returns last)
console.log(0 && 10); // 0 (first falsy)
console.log(null && 'hello'); // null (first falsy)
console.log('hello' && 'world'); // 'world' (both truthy)
// Practical usage
let user = { name: 'John', age: 30 };
console.log(user && user.name); // 'John'
user = null;
console.log(user && user.name); // null (prevents error)
OR (||)
// Returns first truthy value or last value
console.log(true || false); // true
console.log(false || false); // false
console.log(false || true); // true
// Short-circuit evaluation
console.log(5 || 10); // 5 (first truthy)
console.log(0 || 10); // 10 (0 is falsy)
console.log(null || 'default'); // 'default'
console.log('first' || 'second'); // 'first'
// Default values
function greet(name) {
name = name || 'Guest';
return `Hello, ${name}!`;
}
console.log(greet()); // 'Hello, Guest!'
console.log(greet('John')); // 'Hello, John!'
// Chain for fallbacks
let value = null || undefined || 0 || 'found';
console.log(value); // 'found'
NOT (!)
// Inverts boolean value
console.log(!true); // false
console.log(!false); // true
// Convert to boolean
console.log(!0); // true
console.log(!1); // false
console.log(!''); // true
console.log(!'hello'); // false
// Double NOT for boolean conversion
console.log(!!0); // false
console.log(!!1); // true
console.log(!!'hello'); // true
console.log(!!''); // false
// Practical usage
let isLoggedIn = false;
if (!isLoggedIn) {
console.log('Please log in');
}
Nullish Coalescing (??)
// Returns right side only if left is null or undefined
// Unlike ||, it doesn't treat 0, '', false as falsy
console.log(null ?? 'default'); // 'default'
console.log(undefined ?? 'default'); // 'default'
console.log(0 ?? 'default'); // 0
console.log('' ?? 'default'); // ''
console.log(false ?? 'default'); // false
// Difference from ||
console.log(0 || 100); // 100 (0 is falsy)
console.log(0 ?? 100); // 0 (0 is not null/undefined)
console.log('' || 'text'); // 'text'
console.log('' ?? 'text'); // ''
// Practical usage
function getConfig(userConfig) {
return {
timeout: userConfig?.timeout ?? 5000, // Default 5000
retries: userConfig?.retries ?? 3 // Default 3
};
}
console.log(getConfig({ timeout: 0 }));
// { timeout: 0, retries: 3 } - 0 is kept!
🔀 Conditional (Ternary) Operator
// Syntax: condition ? valueIfTrue : valueIfFalse
let age = 20;
let status = age >= 18 ? 'adult' : 'minor';
console.log(status); // 'adult'
// Instead of if-else
let score = 85;
let grade;
if (score >= 90) {
grade = 'A';
} else {
grade = 'B';
}
// Can be written as:
grade = score >= 90 ? 'A' : 'B';
// Nested ternary (use sparingly!)
let num = 0;
let result = num > 0 ? 'positive' :
num < 0 ? 'negative' :
'zero';
console.log(result); // 'zero'
// In function returns
function getStatus(age) {
return age >= 18 ? 'adult' : 'minor';
}
// With JSX/React
const Greeting = ({ name }) => (
name ? `Hello, ${name}!` : 'Hello, Guest!'
);
🔤 String Operators
// Concatenation with +
let first = 'Hello';
let second = 'World';
console.log(first + ' ' + second); // 'Hello World'
// Template literals (preferred)
let name = 'John';
let age = 30;
console.log(`${name} is ${age} years old`);
// Concatenation with +=
let message = 'Hello';
message += ' ';
message += 'World';
console.log(message); // 'Hello World'
// Number to string conversion
console.log('Score: ' + 100); // 'Score: 100'
console.log(100 + 50 + ' points'); // '150 points'
console.log('Points: ' + 100 + 50); // 'Points: 10050' (!)
// Be careful with mixed operations
console.log(1 + 2 + '3'); // '33' (1+2=3, then '3'+'3')
console.log('1' + 2 + 3); // '123' (all concatenation)
🎯 Type Operators
typeof
// Returns string describing type
console.log(typeof 42); // 'number'
console.log(typeof 'hello'); // 'string'
console.log(typeof true); // 'boolean'
console.log(typeof undefined); // 'undefined'
console.log(typeof null); // 'object' (historical bug)
console.log(typeof {}); // 'object'
console.log(typeof []); // 'object'
console.log(typeof function(){}); // 'function'
console.log(typeof Symbol('id')); // 'symbol'
// Practical usage
function add(a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw new Error('Both arguments must be numbers');
}
return a + b;
}
instanceof
// Checks if object is instance of a class
let arr = [1, 2, 3];
let date = new Date();
let obj = {};
console.log(arr instanceof Array); // true
console.log(date instanceof Date); // true
console.log(obj instanceof Object); // true
console.log(arr instanceof Object); // true (Array extends Object)
// With custom classes
class Person {
constructor(name) {
this.name = name;
}
}
let john = new Person('John');
console.log(john instanceof Person); // true
console.log(john instanceof Object); // true
// Not for primitives
console.log('hello' instanceof String); // false
console.log(5 instanceof Number); // false
in
// Checks if property exists in object
let person = {
name: 'John',
age: 30
};
console.log('name' in person); // true
console.log('email' in person); // false
console.log('toString' in person); // true (inherited)
// With arrays (checks index)
let colors = ['red', 'green', 'blue'];
console.log(0 in colors); // true
console.log(3 in colors); // false
// Difference from hasOwnProperty
console.log(person.hasOwnProperty('name')); // true
console.log(person.hasOwnProperty('toString')); // false (inherited)
🔢 Bitwise Operators
// Operate on 32-bit binary representations
console.log(5 & 1); // 1 (AND)
console.log(5 | 1); // 5 (OR)
console.log(5 ^ 1); // 4 (XOR)
console.log(~5); // -6 (NOT)
console.log(5 << 1); // 10 (Left shift)
console.log(5 >> 1); // 2 (Right shift)
console.log(-5 >>> 1); // 2147483645 (Unsigned right shift)
// Practical uses
// Check if number is even
function isEven(num) {
return (num & 1) === 0;
}
// Multiply by 2
function double(num) {
return num << 1;
}
// Divide by 2
function half(num) {
return num >> 1;
}
// Swap without temp variable
let a = 5;
let b = 10;
a = a ^ b;
b = a ^ b;
a = a ^ b;
console.log(a, b); // 10, 5
📊 Operator Precedence
// Operators have different precedence levels
console.log(2 + 3 * 4); // 14 (not 20) - * before +
console.log((2 + 3) * 4); // 20 (parentheses first)
// Order (highest to lowest):
// 1. Grouping: ()
// 2. Member access: . []
// 3. Call/Create: () new
// 4. Postfix: ++ --
// 5. Prefix: ++ -- ! typeof + -
// 6. Exponentiation: **
// 7. Multiply/Divide: * / %
// 8. Add/Subtract: + -
// 9. Shift: << >> >>>
// 10. Relational: < <= > >= in instanceof
// 11. Equality: == != === !==
// 12. Bitwise AND: &
// 13. Bitwise XOR: ^
// 14. Bitwise OR: |
// 15. Logical AND: &&
// 16. Logical OR: ||
// 17. Conditional: ?:
// 18. Assignment: = += -= *= /= etc.
// 19. Comma: ,
// Examples
let result = 10 + 5 * 2; // 20 (5*2=10, 10+10=20)
let value = 10 > 5 && 20 > 15; // true
let mixed = 3 + 4 * 5 / 3; // 9.666... (4*5=20, 20/3=6.67, 3+6.67=9.67)
// Use parentheses for clarity!
let clear = (3 + 4) * (5 / 3);
💡 Practical Examples
Safe Navigation
// Optional chaining (?.) - ES2020
let user = {
name: 'John',
address: {
city: 'New York'
}
};
console.log(user?.address?.city); // 'New York'
console.log(user?.contact?.phone); // undefined (no error!)
// With arrays
let users = [{ name: 'John' }];
console.log(users?.[0]?.name); // 'John'
console.log(users?.[5]?.name); // undefined
// With functions
let greet = null;
console.log(greet?.()); // undefined (no error!)
greet = () => 'Hello';
console.log(greet?.()); // 'Hello'
Smart Defaults
function createUser(options = {}) {
return {
name: options.name ?? 'Anonymous',
age: options.age ?? 18,
role: options.role || 'user',
isActive: options.isActive ?? true
};
}
console.log(createUser());
// { name: 'Anonymous', age: 18, role: 'user', isActive: true }
console.log(createUser({ name: 'John', age: 0 }));
// { name: 'John', age: 0, role: 'user', isActive: true }
// age: 0 is kept because of ??
Value Validation
function validateInput(value) {
// Check existence
if (value === null || value === undefined) {
return 'Value is required';
}
// Type check
if (typeof value !== 'string') {
return 'Value must be a string';
}
// Length check
if (value.length < 3 || value.length > 20) {
return 'Value must be between 3 and 20 characters';
}
return 'Valid';
}
console.log(validateInput('John')); // 'Valid'
console.log(validateInput('Jo')); // 'Value must be...'
console.log(validateInput(123)); // 'Value must be a string'
Flag Toggling
let isDarkMode = false;
// Toggle with !
isDarkMode = !isDarkMode;
console.log(isDarkMode); // true
isDarkMode = !isDarkMode;
console.log(isDarkMode); // false
// Toggle in object
let settings = { darkMode: false };
settings.darkMode = !settings.darkMode;
// Multiple flags with bitwise
const READ = 1; // 001
const WRITE = 2; // 010
const EXECUTE = 4; // 100
let permissions = READ | WRITE; // 011 (3)
console.log(permissions & READ); // 1 (has read)
console.log(permissions & EXECUTE); // 0 (no execute)
permissions |= EXECUTE; // Add execute
console.log(permissions); // 7 (111)
🎯 Key Takeaways
- Arithmetic: +, -, *, /, % for basic math; ** for exponentiation
- === vs ==: Always prefer strict equality (===) over loose (==)
- Logical operators: && returns first falsy or last value; || returns first truthy or last
- ??: Nullish coalescing only treats null/undefined as falsy, not 0 or ''
- Ternary: condition ? ifTrue : ifFalse for concise conditionals
- Optional chaining: ?. prevents errors when accessing nested properties
- Short-circuit: && and || evaluate left to right and stop when result is determined
- Precedence: Use parentheses for clarity, don't rely on memorizing precedence