// Basic arithmeticconsole.log(10 + 5); // 15console.log(10 - 5); // 5console.log(10 * 5); // 50console.log(10 / 5); // 2console.log(10 % 3); // 1 (remainder)console.log(2 ** 3); // 8 (exponentiation)// Increment/Decrementlet x = 5;console.log(x++); // 5 (returns old value, then increments)console.log(x); // 6console.log(++x); // 7 (increments, then returns new value)console.log(x--); // 7 (returns old value, then decrements)console.log(--x); // 5 (decrements, then returns new value)// String concatenation with +console.log("Hello" + " " + "World"); // "Hello World"console.log("5" + 3); // "53" (string concatenation)console.log(5 + "3"); // "53"console.log("5" + 3 + 2); // "532"console.log(5 + 3 + "2"); // "82" (left to right: 5+3=8, then 8+"2"="82")// Type coercion with other operatorsconsole.log("10" - 5); // 5 (string to number)console.log("10" * "2"); // 20console.log("10" / "2"); // 5console.log("10" % 3); // 1// Unary operatorsconsole.log(+"42"); // 42 (string to number)console.log(+"abc"); // NaNconsole.log(-"5"); // -5// Special valuesconsole.log(5 / 0); // Infinityconsole.log(-5 / 0); // -Infinityconsole.log(0 / 0); // NaNconsole.log(NaN + 10); // NaN (NaN propagates)console.log(Infinity - 1); // Infinity
2. Assignment Operators and Compound Assignment
Operator
Name
Equivalent
Example
Result
=
Simple Assignment
N/A
x = 5
x is 5
+=
Addition Assignment
x = x + y
x += 3
Adds and assigns
-=
Subtraction Assignment
x = x - y
x -= 3
Subtracts and assigns
*=
Multiplication Assignment
x = x * y
x *= 3
Multiplies and assigns
/=
Division Assignment
x = x / y
x /= 3
Divides and assigns
%=
Remainder Assignment
x = x % y
x %= 3
Remainder and assigns
**=
Exponentiation Assignment
x = x ** y
x **= 3
Exponentiates and assigns
<<=
Left Shift Assignment
x = x << y
x <<= 2
Left shift and assigns
>>=
Right Shift Assignment
x = x >> y
x >>= 2
Right shift and assigns
>>>=
Unsigned Right Shift Assignment
x = x >>> y
x >>>= 2
Unsigned shift and assigns
&=
Bitwise AND Assignment
x = x & y
x &= 3
AND and assigns
|=
Bitwise OR Assignment
x = x | y
x |= 3
OR and assigns
^=
Bitwise XOR Assignment
x = x ^ y
x |= 3
XOR and assigns
Feature
Description
Example
Destructuring Assignment
Unpack values from arrays/objects
[a, b] = [1, 2], {x, y} = obj
Multiple Assignment
Chain assignments (right-to-left)
a = b = c = 5 (all get 5)
Return Value
Assignment returns assigned value
y = (x = 5) (both are 5)
Compound Benefits
Shorter, clearer, evaluates left side once
arr[i++] += 5 increments i once
Example: Assignment operators
// Simple assignmentlet x = 10;// Compound assignmentsx += 5; // x = x + 5; x is now 15x -= 3; // x = x - 3; x is now 12x *= 2; // x = x * 2; x is now 24x /= 4; // x = x / 4; x is now 6x %= 5; // x = x % 5; x is now 1x **= 3; // x = x ** 3; x is now 1// String concatenation with +=let str = "Hello";str += " World"; // str is "Hello World"// Multiple assignment (right-to-left)let a, b, c;a = b = c = 5; // All are 5console.log(a, b, c); // 5 5 5// Assignment returns valuelet y = (x = 10); // x is 10, y is 10console.log(x, y); // 10 10// Destructuring assignmentlet [p, q] = [1, 2];console.log(p, q); // 1 2let {name, age} = {name: "John", age: 30};console.log(name, age); // "John" 30// Compound assignment with side effectslet arr = [10, 20, 30];let i = 0;arr[i++] += 5; // arr[0] becomes 15, then i incrementsconsole.log(arr[0], i); // 15 1// Swapping with destructuringlet m = 1, n = 2;[m, n] = [n, m]; // Swapconsole.log(m, n); // 2 1
Warning: Always use === and !== (strict equality) to avoid unexpected
type coercion bugs. Use == only when you specifically need type coercion.
4. Logical Operators and Short-circuit Evaluation
Operator
Name
Returns
Short-circuits
Use Case
&&
Logical AND
First falsy value or last value
✓ If left is falsy
Both conditions must be true
||
Logical OR
First truthy value or last value
✓ If left is truthy
At least one condition must be true
!
Logical NOT
Boolean (inverted)
✗ No
Inverts truthiness
!!
Double NOT
Boolean conversion
✗ No
Convert to boolean explicitly
Expression
Result
Explanation
true && true
true
Both truthy → returns last value
true && false
false
Right is falsy → returns false
false && true
false
Short-circuits at false (left)
5 && "hello"
"hello"
Both truthy → returns last
0 && "hello"
0
First falsy → returns 0
true || false
true
Short-circuits at first truthy
false || true
true
Returns first truthy value
false || false
false
Both falsy → returns last
5 || "hello"
5
First truthy → short-circuits
0 || "hello"
"hello"
First falsy, returns second
!true
false
Inverts boolean
!0
true
0 is falsy, inverted to true
!!"hello"
true
Convert to boolean: truthy
Example: Logical operators and short-circuit evaluation
// Logical AND (&&) - returns first falsy or last valueconsole.log(true && true); // trueconsole.log(true && false); // falseconsole.log(5 && 10); // 10 (both truthy, returns last)console.log(0 && 10); // 0 (first falsy)console.log(null && "hello"); // null (first falsy)// Logical OR (||) - returns first truthy or last valueconsole.log(false || true); // trueconsole.log(false || false); // false (last value)console.log(5 || 10); // 5 (first truthy)console.log(0 || 10); // 10 (first falsy, returns second)console.log(null || "default"); // "default" (first falsy)// Logical NOT (!)console.log(!true); // falseconsole.log(!false); // trueconsole.log(!0); // true (0 is falsy)console.log(!""); // true ("" is falsy)console.log(!"hello"); // false ("hello" is truthy)// Double NOT (!!) - convert to booleanconsole.log(!!"hello"); // trueconsole.log(!!0); // falseconsole.log(!!""); // falseconsole.log(!!{}); // true (objects are truthy)// Short-circuit evaluation - practical uses// 1. Default values (before ?? was added)let username = input || "Guest"; // If input is falsy, use "Guest"// 2. Conditional executionisLoggedIn && showDashboard(); // Execute if truthyhasError || showSuccessMessage(); // Execute if falsy// 3. Guard clausesfunction processUser(user) { user && user.profile && console.log(user.profile.name); // Only accesses nested property if all are truthy}// 4. Avoiding function callslet result = expensiveCheck() || cachedValue;// If expensiveCheck() is truthy, cachedValue never evaluated// Short-circuit prevents errorslet obj = null;let value = obj && obj.property; // undefined (doesn't throw)// Without short-circuit: obj.property would throw error// Combining operatorslet access = isAdmin || (isPremium && hasPermission);console.log(true || (false && error())); // true, error() not called// Falsy values: false, 0, "", null, undefined, NaNconsole.log(false || 0 || "" || null || undefined || NaN || "found");// "found" (first truthy)
Note: Logical operators return the actual value (not just boolean). Short-circuit evaluation
stops at first definitive result, useful for default values and conditional execution.
5. Bitwise Operators and Binary Operations
Operator
Name
Description
Example
Binary
Result
&
AND
1 if both bits are 1
5 & 3
0101 & 0011
1 (0001)
|
OR
1 if at least one bit is 1
5 | 3
0101 | 0011
7 (0111)
^
XOR
1 if bits are different
5 ^ 3
0101 ^ 0011
6 (0110)
~
NOT
Inverts all bits
~5
~0101
-6 (two's complement)
<<
Left Shift
Shifts bits left, fills 0s
5 << 1
0101 → 1010
10
>>
Sign-propagating Right Shift
Shifts bits right, preserves sign
5 >> 1
0101 → 0010
2
>>>
Zero-fill Right Shift
Shifts bits right, fills 0s
-5 >>> 1
Fills with 0s
Large positive number
Use Case
Operation
Example
Purpose
Check if even
n & 1
5 & 1 = 1 (odd), 4 & 1 = 0 (even)
Fast even/odd check
Multiply by 2n
n << x
5 << 2 = 20 (5 × 4)
Fast multiplication
Divide by 2n
n >> x
20 >> 2 = 5 (20 ÷ 4)
Fast division
Toggle bit
n ^ (1 << i)
Toggles i-th bit
Flags/permissions
Set bit
n | (1 << i)
Sets i-th bit to 1
Enable flag
Clear bit
n & ~(1 << i)
Sets i-th bit to 0
Disable flag
Check bit
(n >> i) & 1
Gets value of i-th bit
Test flag
Swap variables
a ^= b; b ^= a; a ^= b;
Swap without temp variable
XOR swap trick
Example: Bitwise operations
// Basic bitwise operationsconsole.log(5 & 3); // 1 (0101 & 0011 = 0001)console.log(5 | 3); // 7 (0101 | 0011 = 0111)console.log(5 ^ 3); // 6 (0101 ^ 0011 = 0110)console.log(~5); // -6 (inverts bits, two's complement)// Bit shiftsconsole.log(5 << 1); // 10 (0101 → 1010) multiply by 2console.log(5 << 2); // 20 (0101 → 10100) multiply by 4console.log(10 >> 1); // 5 (1010 → 0101) divide by 2console.log(20 >> 2); // 5 (10100 → 0101) divide by 4// Practical use cases// 1. Check if number is even or oddfunction isEven(n) { return (n & 1) === 0;}console.log(isEven(4)); // trueconsole.log(isEven(5)); // false// 2. Flags and permissionsconst READ = 1; // 001const WRITE = 2; // 010const EXECUTE = 4; // 100let permissions = 0;permissions |= READ; // Add READ permissionpermissions |= WRITE; // Add WRITE permissionconsole.log(permissions & READ); // Check if READ (non-zero = true)console.log(permissions & EXECUTE); // Check if EXECUTE (0 = false)permissions &= ~WRITE; // Remove WRITE permissionconsole.log(permissions); // 1 (only READ)// 3. Fast integer conversionconsole.log(~~3.14); // 3 (double NOT truncates decimals)console.log(5.7 | 0); // 5 (OR with 0 truncates)console.log(5.7 >> 0); // 5 (right shift by 0 truncates)// 4. XOR swap (without temp variable)let a = 5, b = 10;a ^= b; // a = 5 ^ 10b ^= a; // b = 10 ^ (5 ^ 10) = 5a ^= b; // a = (5 ^ 10) ^ 5 = 10console.log(a, b); // 10 5// 5. Toggle booleanlet flag = true;flag ^= 1; // false (1 ^ 1 = 0)flag ^= 1; // true (0 ^ 1 = 1)// 6. Set specific bitlet n = 0b0000; // Binary literaln |= (1 << 2); // Set bit 2: 0b0100console.log(n.toString(2)); // "100"// 7. Clear specific bitn &= ~(1 << 2); // Clear bit 2: 0b0000console.log(n.toString(2)); // "0"
Note: Bitwise operators work on 32-bit integers. Common uses include flags, permissions, fast
math operations, and low-level data manipulation.
6. Optional Chaining (?.) and Nullish Coalescing (??)
Operator
Syntax
Returns
Use Case
?. ES2020
obj?.prop
undefined if obj is null/undefined, else obj.prop
Safe property access
?.[]
obj?.[expr]
undefined if obj is null/undefined
Safe dynamic property access
?.()
func?.(args)
undefined if func is null/undefined
Safe function call
?? ES2020
a ?? b
a if not null/undefined, else b
Default values for null/undefined only
Feature
|| (OR)
?? (Nullish Coalescing)
Falsy values treated as missing
Yes (false, 0, "", null, undefined, NaN)
No (only null/undefined)
0 || 100
100
0
"" || "default"
"default"
""
false || true
true
false
null ?? 100
100
100
undefined ?? 100
100
100
Use case
When any falsy should use default
When only null/undefined should use default
Example: Optional chaining and nullish coalescing
// Optional Chaining (?.)// Without optional chaining (verbose and error-prone)let user = null;// let name = user.profile.name; // TypeError: Cannot read property 'profile' of nulllet name = user && user.profile && user.profile.name; // undefined// With optional chaining (concise and safe)name = user?.profile?.name; // undefined (no error)const user2 = { profile: { name: "Alice", address: { city: "NYC" } }};console.log(user2?.profile?.name); // "Alice"console.log(user2?.profile?.address?.city); // "NYC"console.log(user2?.profile?.phone); // undefined (no error)console.log(user2?.account?.balance); // undefined// Optional chaining with arraysconst arr = null;console.log(arr?.[0]); // undefined (safe)console.log(user2?.tags?.[0]); // undefined// Optional chaining with function callsconst obj = { method: function() { return "called"; }};console.log(obj.method?.()); // "called"console.log(obj.nonExistent?.()); // undefined (no error)console.log(user?.getProfile?.()); // undefined// Nullish Coalescing (??)// Problem with || operatorlet count = 0;let value1 = count || 10; // 10 (0 is falsy, uses default)let value2 = count ?? 10; // 0 (0 is not null/undefined)let text = "";let msg1 = text || "default"; // "default" ("" is falsy)let msg2 = text ?? "default"; // "" (empty string is valid)// Use ?? for actual null/undefined checkslet config = { timeout: 0, // 0 is valid enabled: false, // false is valid name: "" // empty string is valid};let timeout = config.timeout ?? 3000; // 0 (not null/undefined)let enabled = config.enabled ?? true; // false (not null/undefined)let name = config.name ?? "Unnamed"; // "" (not null/undefined)let missing = config.missing ?? "N/A"; // "N/A" (undefined)// Combining ?. and ??const data = { user: null, settings: { theme: "dark" }};let theme = data?.settings?.theme ?? "light"; // "dark"let userName = data?.user?.name ?? "Guest"; // "Guest"// Real-world example: API responsefunction getUserCity(response) { return response?.data?.user?.address?.city ?? "Unknown";}console.log(getUserCity(null)); // "Unknown"console.log(getUserCity({ data: null })); // "Unknown"console.log(getUserCity({ data: { user: { address: { city: "NYC" } } }})); // "NYC"// Short-circuit evaluationlet expensiveFn = () => { console.log("Called"); return 42; };let result = null?.property?.method?.(); // undefined (expensiveFn not called)console.log(result); // undefined
Warning: Don't overuse ?. as it can hide bugs. Use it for genuinely optional
properties, not to mask errors in required data.
7. Logical Assignment Operators (||=, &&=, ??=)
Operator
Name
Equivalent
Assigns When
||= ES2021
Logical OR Assignment
x || (x = y)
x is falsy
&&= ES2021
Logical AND Assignment
x && (x = y)
x is truthy
??= ES2021
Nullish Assignment
x ?? (x = y)
x is null or undefined
Operator
Behavior
Use Case
Example
||=
Assigns if current value is falsy
Set default for any falsy value
x ||= 10 (assigns if x is falsy)
&&=
Assigns if current value is truthy
Update existing truthy value
x &&= 10 (assigns if x is truthy)
??=
Assigns only if null/undefined
Set default only for null/undefined
x ??= 10 (assigns if x is null/undefined)
Before ES2021:
// Logical OR patternx = x || defaultValue;if (!x) x = defaultValue;// Logical AND patternx = x && newValue;if (x) x = newValue;// Nullish patternx = x ?? defaultValue;if (x == null) x = defaultValue;
With ES2021:
// Logical OR assignmentx ||= defaultValue;// Logical AND assignmentx &&= newValue;// Nullish assignmentx ??= defaultValue;
Example: Logical assignment operators
// ||= Logical OR Assignment// Assigns if left side is falsylet a = 0;a ||= 10; // a is 10 (0 is falsy)let b = 5;b ||= 10; // b is still 5 (5 is truthy)let c = "";c ||= "default"; // c is "default" ("" is falsy)// &&= Logical AND Assignment// Assigns if left side is truthylet x = 5;x &&= 10; // x is 10 (5 is truthy)let y = 0;y &&= 10; // y is still 0 (0 is falsy, no assignment)let z = null;z &&= 10; // z is still null (null is falsy)// ??= Nullish Assignment// Assigns only if null or undefinedlet p = 0;p ??= 10; // p is still 0 (0 is not null/undefined)let q = null;q ??= 10; // q is 10 (null)let r = undefined;r ??= 10; // r is 10 (undefined)let s = false;s ??= true; // s is still false (false is not null/undefined)// Practical use cases// 1. Object property defaults with ??=const config = { timeout: 0, // 0 is valid retry: null // null should be replaced};config.timeout ??= 3000; // Still 0 (not null/undefined)config.retry ??= 3; // Now 3 (was null)config.newProp ??= "default"; // "default" (was undefined)console.log(config);// { timeout: 0, retry: 3, newProp: "default" }// 2. Accumulation with &&=let total = 100;let applyDiscount = true;total &&= total * 0.9; // Apply 10% discount if total existsconsole.log(total); // 90let nullTotal = null;nullTotal &&= nullTotal * 0.9; // No operation (nullTotal is falsy)console.log(nullTotal); // null (unchanged)// 3. Cache pattern with ||=let cache = {};function getData(key) { // Set cache if not already set cache[key] ||= expensiveOperation(key); return cache[key];}function expensiveOperation(key) { console.log("Computing..."); return key * 2;}console.log(getData(5)); // "Computing..." then 10console.log(getData(5)); // 10 (from cache, no computing)// 4. Updating objects conditionallyconst user = { name: "Alice", age: null, status: undefined};user.name ||= "Anonymous"; // Still "Alice" (truthy)user.age ??= 18; // Now 18 (was null)user.status ??= "active"; // Now "active" (was undefined)// 5. Short-circuit: right side not evaluated if condition not metlet count = 0;let getValue = () => { count++; return 100; };let x1 = 5;x1 ||= getValue(); // getValue() NOT called (x1 is truthy)console.log(count); // 0let x2 = 0;x2 ||= getValue(); // getValue() IS called (x2 is falsy)console.log(count); // 1
Note: Logical assignment operators combine logical operations with assignment, providing
cleaner syntax and short-circuit evaluation (right side only evaluated when assignment occurs).
Section 4 Summary
Arithmetic operators include +, -, *, /, %, ** (exponentiation);
+ concatenates strings if either operand is string
Assignment operators support compound forms (+=, -=, *=, etc.) for concise
update operations
Use strict equality (===, !==) to avoid type coercion bugs; loose equality
(==) performs type conversion
Logical operators (&&, ||, !) short-circuit and return actual values, not
just booleans; useful for defaults and guards
Bitwise operators work on 32-bit integers; useful for flags, permissions,
and fast math operations
Optional chaining (?.) safely accesses nested properties; nullish coalescing (??) provides defaults only for null/undefined
Logical assignment (||=, &&=, ??=) combines logic with assignment;
short-circuits when assignment unnecessary