Docs LogoDocs

Operators - Performing Operations on Data

Documentation for Operators - Performing Operations on Data.

Operators - Performing Operations on Data

What are Operators?

Operators are symbols that perform operations on values (operands). They are the building blocks for creating expressions and performing calculations.

// Example: 5 + 3
// 5 and 3 are operands
// + is the operator
// Result: 8

Operator Classification

JavaScript Operators

├─ 1. Arithmetic Operators
├─ 2. Assignment Operators
├─ 3. Comparison Operators
├─ 4. Logical Operators
├─ 5. String Operators
├─ 6. Conditional (Ternary) Operator
├─ 7. Type Operators
├─ 8. Bitwise Operators
└─ 9. Special Operators

Types of Operators - Quick Reference

TypeOperatorsPurpose
Arithmetic+ - * / % ** ++ --Math operations
Assignment= += -= *= /= %=Assign values
Comparison== === != !== > < >= <=Compare values
Logical&& || ! ??Boolean logic
String+Concatenation
Ternary? :Conditional
Typetypeof instanceof inCheck types
Bitwise& | ^ ~ << >> >>>Bit manipulation
Special?. ... delete void ,Special purposes

1. Arithmetic Operators

Perform mathematical calculations on numeric values.

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.333... (Division)
console.log(a % b); // 1  (Modulus - remainder)
console.log(a ** b); // 1000 (Exponentiation - 10^3)

Arithmetic Operators Table

OperatorNameExampleResultDescription
+Addition5 + 38Adds two numbers
-Subtraction5 - 32Subtracts second from first
*Multiplication5 * 315Multiplies two numbers
/Division10 / 25Divides first by second
%Modulus10 % 31Returns division remainder
**Exponentiation2 ** 38Raises first to power of second
++Incrementx++x + 1Increases value by 1
--Decrementx--x - 1Decreases value by 1

Increment & Decrement Operators

let x = 5;

// Post-increment (use then increment)
console.log(x++); // 5 (returns 5, then x becomes 6)
console.log(x); // 6

// Pre-increment (increment then use)
console.log(++x); // 7 (x becomes 7, then returns 7)
console.log(x); // 7

// Post-decrement
console.log(x--); // 7 (returns 7, then x becomes 6)
console.log(x); // 6

// Pre-decrement
console.log(--x); // 5 (x becomes 5, then returns 5)
console.log(x); // 5

Comparison: Pre vs Post Increment

OperatorNameWhen ChangesReturnsExample
x++Post-incrementAfter statementOld valuelet y = x++ → y gets old x
++xPre-incrementBefore statementNew valuelet y = ++x → y gets new x
x--Post-decrementAfter statementOld valuelet y = x-- → y gets old x
--xPre-decrementBefore statementNew valuelet y = --x → y gets new x

Unary Plus and Minus

// Unary plus converts to number
console.log(+"5"); // 5 (string to number)
console.log(+true); // 1 (boolean to number)
console.log(+false); // 0

// Unary minus negates and converts
console.log(-"5"); // -5
console.log(-true); // -1

Interview Example:

let a = 5;
let b = a++ + ++a; // What is b?

// Step by step:
// a++ returns 5, then a becomes 6
// ++a makes a = 7, returns 7
// b = 5 + 7 = 12
// Final: a = 7, b = 12

console.log(a); // 7
console.log(b); // 12

Special Cases

// Division by zero
console.log(10 / 0); // Infinity
console.log(-10 / 0); // -Infinity

// NaN (Not a Number)
console.log("hello" * 5); // NaN
console.log(0 / 0); // NaN

// Precision issues
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false

// Solution for precision
console.log((0.1 * 10 + 0.2 * 10) / 10); // 0.3
console.log((0.1 + 0.2).toFixed(2)); // "0.30"

2. Assignment Operators

Assign values to variables.

Assignment Operators Table

OperatorNameExampleEquivalent toResult
=Assignmentx = 5-x = 5
+=Addition assignmentx += 5x = x + 5x = 15
-=Subtraction assignmentx -= 3x = x - 3x = 12
*=Multiplication assignmentx *= 2x = x * 2x = 24
/=Division assignmentx /= 4x = x / 4x = 6
%=Modulus assignmentx %= 4x = x % 4x = 2
**=Exponentiation assignmentx **= 3x = x ** 3x = 8

Basic Assignment

let x = 10; // Assigns 10 to x

Compound Assignment

let x = 10;

x += 5; // x = x + 5  → 15
console.log(x); // 15

x -= 3; // x = x - 3  → 12
console.log(x); // 12

x *= 2; // x = x * 2  → 24
console.log(x); // 24

x /= 4; // x = x / 4  → 6
console.log(x); // 6

x %= 4; // x = x % 4  → 2
console.log(x); // 2

x **= 3; // x = x ** 3 → 8
console.log(x); // 8

Chained Assignment

// Assign same value to multiple variables
let a, b, c;
a = b = c = 10;

console.log(a); // 10
console.log(b); // 10
console.log(c); // 10

// Right to left evaluation
let x = (y = 5); // y gets 5, then x gets y's value
console.log(x); // 5
console.log(y); // 5

Destructuring Assignment

// Array destructuring
let [first, second] = [1, 2];
console.log(first); // 1
console.log(second); // 2

// Object destructuring
let { name, age } = { name: "John", age: 25 };
console.log(name); // 'John'
console.log(age); // 25

// Swap variables
let a = 1,
  b = 2;
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1

3. Comparison Operators

Compare two values and return boolean (true/false).

Comparison Operators Table

OperatorNameExampleResultDescription
==Equal (loose)5 == '5'trueCompares values (with type coercion)
===Equal (strict)5 === '5'falseCompares values and types
!=Not equal (loose)5 != '5'falseChecks inequality (with coercion)
!==Not equal (strict)5 !== '5'trueChecks inequality (no coercion)
>Greater than10 > 5trueChecks if left > right
<Less than10 < 5falseChecks if left < right
>=Greater than or equal10 >= 10trueChecks if left >= right
<=Less than or equal5 <= 10trueChecks if left <= right

== vs === (Critical Interview Topic!)

Loose Equality (==) - Converts types before comparing
Strict Equality (===) - No type conversion

// Loose equality (==) - type coercion happens
console.log(5 == "5"); // true (string '5' converted to number)
console.log(0 == false); // true (false converted to 0)
console.log("" == false); // true (both converted to 0)
console.log(null == undefined); // true (special case)
console.log(1 == true); // true (true converted to 1)
console.log("0" == false); // true (both converted to 0)

// Strict equality (===) - no type conversion
console.log(5 === "5"); // false (different types)
console.log(0 === false); // false (different types)
console.log("" === false); // false (different types)
console.log(null === undefined); // false (different types)
console.log(1 === true); // false (different types)

Detailed Comparison Table: == vs ===

Comparison== Result=== ResultReason
5 == '5'truefalse== converts string to number
0 == falsetruefalse== converts false to 0
'' == falsetruefalse== converts both to 0
null == undefinedtruefalse== special rule
NaN == NaNfalsefalseNaN never equals itself
[] == falsetruefalse== converts [] to 0
'0' == 0truefalse== converts string to number

Best Practice: Always use === and !== to avoid unexpected behavior.

Greater/Less Than Comparisons

// Number comparisons
console.log(10 > 5); // true
console.log(10 < 5); // false
console.log(10 >= 10); // true
console.log(5 <= 10); // true

// String comparisons (lexicographical)
console.log("apple" < "banana"); // true
console.log("Z" < "a"); // true (uppercase < lowercase in ASCII)
console.log("10" < "9"); // true (string comparison, not numeric)

// Mixed type comparisons
console.log("10" > 5); // true ('10' converted to 10)
console.log("5" < 10); // true ('5' converted to 5)

// Special cases
console.log(null > 0); // false
console.log(null == 0); // false
console.log(null >= 0); // true (weird!)

console.log(undefined > 0); // false
console.log(undefined < 0); // false
console.log(undefined == 0); // false

Special Comparison Cases

// NaN comparisons
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true (correct way)
console.log(isNaN(NaN)); // true

// +0 vs -0
console.log(+0 === -0); // true
console.log(Object.is(+0, -0)); // false (can distinguish)

// null and undefined
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(null == 0); // false (special case)
console.log(undefined == 0); // false

4. Logical Operators

Combine or invert boolean values.

Logical Operators Table

OperatorNameReturnsShort-circuitsExample
&&Logical ANDFirst falsy or last valueYestrue && 'hello''hello'
||Logical ORFirst truthy or last valueYesfalse || 'hi''hi'
!Logical NOTBooleanNo!truefalse
??Nullish CoalescingFirst non-nullish valueYesnull ?? 'default''default'

AND Operator (&&)

// Both must be true for result to be true
console.log(true && true); // true
console.log(true && false); // false
console.log(false && true); // false
console.log(false && false); // false

// Returns first falsy value or last value
console.log(0 && "hello"); // 0 (first falsy)
console.log("hello" && 0); // 0 (last value)
console.log("hello" && "world"); // 'world' (last value)
console.log(null && "hello"); // null (first falsy)

// Practical example
let age = 25;
let hasLicense = true;

if (age >= 18 && hasLicense) {
  console.log("Can drive"); // Executes if both conditions true
}

// Guard pattern
let user = { name: "John" };
user && console.log(user.name); // 'John' (safe access)

let noUser = null;
noUser && console.log(noUser.name); // null (prevents error)

OR Operator (||)

// At least one must be true for result to be true
console.log(true || true); // true
console.log(true || false); // true
console.log(false || true); // true
console.log(false || false); // false

// Returns first truthy value or last value
console.log("hello" || 0); // 'hello' (first truthy)
console.log(0 || "hello"); // 'hello' (first truthy)
console.log(0 || null); // null (last value)
console.log("hi" || "hello"); // 'hi' (first truthy)

// Practical example
let isWeekend = true;
let isHoliday = false;

if (isWeekend || isHoliday) {
  console.log("No work!"); // Executes if either is true
}

// Default values
let userName = "";
let displayName = userName || "Guest"; // 'Guest'

let count = 0;
let value = count || 10; // 10 (but 0 is valid!)

NOT Operator (!)

// Inverts boolean value
console.log(!true); // false
console.log(!false); // true

// Double NOT converts to boolean
console.log(!!1); // true
console.log(!!0); // false
console.log(!!"hello"); // true
console.log(!!""); // false

// Practical example
let isLoggedIn = false;

if (!isLoggedIn) {
  console.log("Please login"); // Executes if NOT logged in
}

// Negating comparisons
let age = 15;
if (!(age >= 18)) {
  console.log("Minor"); // Executes if NOT adult
}

Nullish Coalescing Operator (??)

// Returns right side only if left is null or undefined
console.log(null ?? "default"); // 'default'
console.log(undefined ?? "default"); // 'default'

// Unlike ||, it doesn't treat 0, false, '' as falsy
console.log(0 ?? 10); // 0 (0 is not null/undefined)
console.log(false ?? true); // false
console.log("" ?? "default"); // '' (empty string is not null/undefined)

// Comparison with ||
let count = 0;
console.log(count || 10); // 10 (|| treats 0 as falsy)
console.log(count ?? 10); // 0 (?? only checks null/undefined)

let value = "";
console.log(value || "default"); // 'default'
console.log(value ?? "default"); // '' (empty string)

// Practical use
let userAge = 0; // 0 is a valid age
let age = userAge ?? 18; // 0 (keeps 0)
let age2 = userAge || 18; // 18 (treats 0 as falsy)

Short-Circuit Evaluation (Interview Topic!)

// && stops at first falsy value
console.log(false && "hello"); // false (doesn't evaluate 'hello')
console.log(true && "hello"); // 'hello' (evaluates and returns)

// Practical: Conditional execution
let isLoggedIn = true;
isLoggedIn && console.log("Welcome!"); // Logs 'Welcome!'

// || stops at first truthy value
console.log(true || "hello"); // true (doesn't evaluate 'hello')
console.log(false || "hello"); // 'hello' (evaluates and returns)

// Practical: Default values
let config = null;
let settings = config || { theme: "light" }; // Uses default

// Can prevent errors
let user = null;
let name = user && user.name; // null (safe, no error)
// let name = user.name; // Error: Cannot read property 'name' of null

// Complex example
function processUser(user) {
  // If no user, return early
  if (!user) return;

  // Process user (short-circuit evaluation)
  user && user.active && console.log("Processing active user");
}

Truth Table

ABA && BA || B!AA ?? B
truetruetruetruefalsetrue
truefalsefalsetruefalsetrue
falsetruefalsetruetruetrue
falsefalsefalsefalsetruefalse
null5null5false5
0505true0

Logical Operator Precedence

// ! has highest precedence, then &&, then ||
console.log(true || (false && false)); // true
console.log((true || false) && false); // false

console.log(!false || true); // true (! first)
console.log(!(false || true)); // false (parentheses first)

// Real-world example
let isAdmin = false;
let isOwner = false;
let isActive = true;

// Without parentheses (wrong!)
if ((isAdmin || isOwner) && isActive) {
  console.log("Access granted");
}

// With parentheses (correct!)
if (isAdmin || (isOwner && isActive)) {
  console.log("Access granted");
}

5. String Operators

Concatenation (+)

let firstName = "John";
let lastName = "Doe";

// String concatenation
let fullName = firstName + " " + lastName; // 'John Doe'
console.log(fullName);

// Concatenation with +=
let greeting = "Hello";
greeting += " ";
greeting += "World";
console.log(greeting); // 'Hello World'

// Number + String = String
console.log(5 + "5"); // '55' (string)
console.log("5" + 5); // '55' (string)
console.log(5 + 5 + "5"); // '105' (5+5=10, then '10'+'5'='105')
console.log("5" + 5 + 5); // '555' ('5'+'5'='55', then '55'+5='555')

// Multi-line concatenation
let message =
  "This is a long message " +
  "that spans multiple lines " +
  "using concatenation.";
console.log(message);

String Concatenation Rules

ExpressionResultExplanation
'5' + 5'55'Number converted to string
5 + '5''55'Number converted to string
'5' + 5 + 5'555'Left to right: '5'+'5'='55', '55'+5='555'
5 + 5 + '5''105'Left to right: 5+5=10, 10+'5'='105'
'Hello' + true'Hellotrue'Boolean converted to string
'5' - 23Subtraction converts strings to numbers

Interview Tip: When + is used with a string, it concatenates. Order matters!

Template Literals (Modern Way)

let name = "John";
let age = 25;

// Old way (concatenation)
let message = "My name is " + name + " and I am " + age + " years old.";

// New way (template literals)
let message2 = `My name is ${name} and I am ${age} years old.`;

console.log(message2); // My name is John and I am 25 years old.

// Expressions inside template literals
let a = 5;
let b = 10;
console.log(`${a} + ${b} = ${a + b}`); // 5 + 10 = 15

// Multi-line strings
let html = `
  <div>
    <h1>${name}</h1>
    <p>Age: ${age}</p>
  </div>
`;

// Function calls
function double(x) {
  return x * 2;
}
console.log(`Double of 5 is ${double(5)}`); // Double of 5 is 10

6. Ternary Operator (Conditional)

Shorthand for if-else statement.

Syntax

condition ? valueIfTrue : valueIfFalse;

Basic Examples

let age = 20;

// Instead of if-else
let status = age >= 18 ? "Adult" : "Minor";
console.log(status); // 'Adult'

// Direct use
console.log(age >= 18 ? "Can vote" : "Cannot vote"); // 'Can vote'

// Assignment
let discount = age >= 65 ? 0.2 : 0;
console.log(discount); // 0

// Multiple conditions
let score = 85;
let grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";
console.log(grade); // 'B'

Nested Ternary (Use Sparingly!)

let score = 85;

// Nested ternary (hard to read)
let grade =
  score >= 90
    ? "A"
    : score >= 80
      ? "B"
      : score >= 70
        ? "C"
        : score >= 60
          ? "D"
          : "F";

console.log(grade); // 'B'

// Better: Use if-else for complex logic
let grade2;
if (score >= 90) {
  grade2 = "A";
} else if (score >= 80) {
  grade2 = "B";
} else if (score >= 70) {
  grade2 = "C";
} else if (score >= 60) {
  grade2 = "D";
} else {
  grade2 = "F";
}

Practical Use Cases

// 1. Conditional rendering (React-style)
let isLoggedIn = true;
let message = isLoggedIn ? "Welcome back!" : "Please login";

// 2. Setting default values
let userRole = undefined;
let role = userRole ? userRole : "guest";

// 3. Conditional CSS class
let isActive = true;
let className = isActive ? "active" : "inactive";

// 4. Inline calculations
let price = 100;
let finalPrice = price > 50 ? price * 0.9 : price; // 10% discount if > 50

// 5. Function parameters
function greet(name) {
  name = name ? name : "Guest"; // Default parameter (old way)
  console.log(`Hello, ${name}!`);
}

// 6. Null/undefined checks
let value = null;
let result = value ? value : "default";

Ternary vs If-Else

FeatureTernary OperatorIf-Else Statement
SyntaxSingle lineMultiple lines
ReadabilityGood for simpleBetter for complex
Returns valueYesNo (needs return)
Use caseAssignments, returnsComplex logic
// Ternary: Returns value directly
let status = age >= 18 ? "Adult" : "Minor";

// If-else: Need assignment
let status2;
if (age >= 18) {
  status2 = "Adult";
} else {
  status2 = "Minor";
}

// Ternary in return statement
function getStatus(age) {
  return age >= 18 ? "Adult" : "Minor";
}

// If-else needs multiple returns
function getStatus2(age) {
  if (age >= 18) {
    return "Adult";
  } else {
    return "Minor";
  }
}

7. Type Operators

typeof Operator

Returns a string indicating the type of a value.

// Primitives
console.log(typeof 42); // 'number'
console.log(typeof 3.14); // 'number'
console.log(typeof NaN); // 'number'
console.log(typeof Infinity); // 'number'

console.log(typeof "hello"); // 'string'
console.log(typeof ""); // 'string'

console.log(typeof true); // 'boolean'
console.log(typeof false); // 'boolean'

console.log(typeof undefined); // 'undefined'

console.log(typeof null); // 'object' (JavaScript bug!)

console.log(typeof Symbol("id")); // 'symbol'

console.log(typeof 123n); // 'bigint'

// Objects
console.log(typeof {}); // 'object'
console.log(typeof []); // 'object'
console.log(typeof function () {}); // 'function'
console.log(typeof new Date()); // 'object'
console.log(typeof /regex/); // 'object'

// Undeclared variables
console.log(typeof undeclaredVar); // 'undefined' (no error!)

typeof Return Values Table

Valuetypeof ReturnsNotes
42, 3.14, NaN'number'All numbers
"hello", '''string'All strings
true, false'boolean'Boolean values
undefined'undefined'Undefined value
null'object'⚠️ Bug! Should be 'null'
Symbol('id')'symbol'Symbol type
123n'bigint'BigInt type
{}'object'Plain object
[]'object'⚠️ Arrays are objects
function(){}'function'Functions
class MyClass {}'function'⚠️ Classes are functions

instanceof Operator

Checks if an object is an instance of a specific constructor/class.

// Arrays
let arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true (arrays are objects)

// Objects
let obj = { name: "John" };
console.log(obj instanceof Object); // true
console.log(obj instanceof Array); // false

// Dates
let date = new Date();
console.log(date instanceof Date); // true
console.log(date instanceof Object); // true

// Functions
function myFunc() {}
console.log(myFunc instanceof Function); // true
console.log(myFunc instanceof Object); // true

// Custom constructors
function Person(name) {
  this.name = name;
}
let john = new Person("John");
console.log(john instanceof Person); // true
console.log(john instanceof Object); // true

// Classes
class User {
  constructor(name) {
    this.name = name;
  }
}
let user = new User("Jane");
console.log(user instanceof User); // true
console.log(user instanceof Object); // true

// Primitives
console.log(5 instanceof Number); // false (primitive, not object)
console.log(new Number(5) instanceof Number); // true (object wrapper)

in Operator

Checks if a property exists in an object.

let person = {
  name: "John",
  age: 25,
};

console.log("name" in person); // true
console.log("age" in person); // true
console.log("salary" in person); // false

// Inherited properties
console.log("toString" in person); // true (inherited from Object)

// Array indices
let arr = [1, 2, 3];
console.log(0 in arr); // true
console.log(3 in arr); // false (index 3 doesn't exist)

// Array length
console.log("length" in arr); // true

Type Checking Best Practices

// Check for number
function isNumber(value) {
  return typeof value === "number" && !isNaN(value);
}

// Check for string
function isString(value) {
  return typeof value === "string";
}

// Check for array (typeof doesn't work!)
function isArray(value) {
  return Array.isArray(value); // ✅ Correct way
  // return typeof value === 'object'; // ❌ Wrong (objects also return 'object')
}

// Check for object (not array, not null)
function isObject(value) {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

// Check for null
function isNull(value) {
  return value === null; // ✅ Correct way
  // return typeof value === 'object'; // ❌ Wrong (objects also return 'object')
}

// Check for undefined
function isUndefined(value) {
  return typeof value === "undefined";
}

// Check for function
function isFunction(value) {
  return typeof value === "function";
}

8. Operator Precedence

Determines the order in which operations are performed.

Precedence Table (High to Low)

LevelOperatorNameAssociativity
1()GroupingN/A
2. [] ()Member/CallLeft-to-right
3newCreate instance (with args)N/A
4++ --Postfix increment/decrementN/A
5! ~ + - ++ -- typeof deleteUnaryRight-to-left
6**ExponentiationRight-to-left
7* / %MultiplicativeLeft-to-right
8+ -AdditiveLeft-to-right
9<< >> >>>Bitwise shiftLeft-to-right
10< <= > >= in instanceofRelationalLeft-to-right
11== === != !==EqualityLeft-to-right
12&Bitwise ANDLeft-to-right
13^Bitwise XORLeft-to-right
14|Bitwise ORLeft-to-right
15&&Logical ANDLeft-to-right
16||Logical ORLeft-to-right
17??Nullish coalescingLeft-to-right
18? :Conditional (ternary)Right-to-left
19= += -= etc.AssignmentRight-to-left
20,CommaLeft-to-right

Examples

// Without parentheses
let result = 2 + 3 * 4; // 14 (multiplication first)
console.log(result);

// With parentheses
let result2 = (2 + 3) * 4; // 20 (addition first)
console.log(result2);

// Multiple operators
let x = 10 - 5 * 2; // 0 (5*2=10, then 10-10=0)
console.log(x);

let y = (10 - 5) * 2; // 10 ((10-5)=5, then 5*2=10)
console.log(y);

// Exponentiation is right-to-left
console.log(2 ** (3 ** 2)); // 512 (2^(3^2) = 2^9 = 512)
console.log((2 ** 3) ** 2); // 64 ((2^3)^2 = 8^2 = 64)

// Logical operators
console.log(true || (false && false)); // true (&& before ||)
console.log((true || false) && false); // false (parentheses first)

Complex Example

let x = 5;
let y = x++ + ++x * 2; // What is y?

// Step-by-step breakdown:
// 1. x++ returns 5, then x becomes 6 (postfix increment)
// 2. ++x makes x = 7, returns 7 (prefix increment)
// 3. 7 * 2 = 14 (multiplication has higher precedence)
// 4. 5 + 14 = 19 (addition)
// Final: x = 7, y = 19

console.log(x); // 7
console.log(y); // 19

Associativity Examples

// Left-to-right (addition)
let result = 5 - 3 - 1; // (5 - 3) - 1 = 1
console.log(result); // 1

// Right-to-left (assignment)
let a, b, c;
a = b = c = 5; // c = 5, then b = c, then a = b
console.log(a, b, c); // 5 5 5

// Right-to-left (exponentiation)
console.log(2 ** (3 ** 2)); // 2 ** (3 ** 2) = 2 ** 9 = 512

Precedence Best Practices

// ✅ Good: Use parentheses for clarity
let result = price * quantity + tax;

// ❌ Bad: Relies on knowing precedence
let result = price * quantity + tax;

// ✅ Good: Clear intention
if ((isAdmin || isOwner) && isActive) {
  // ...
}

// ❌ Bad: Confusing without parentheses
if (isAdmin || (isOwner && isActive)) {
  // ...
}

// ✅ Good: Break complex expressions
let subtotal = price * quantity;
let total = subtotal + tax;

// ❌ Bad: Everything in one line
let total = price * quantity + tax + (discount ? -discount : 0);

9. Special Operators

Optional Chaining (?.)

Safely access nested object properties without checking each level.

// Without optional chaining
let user = null;
// let city = user.address.city; // Error: Cannot read property 'address' of null

// Traditional solution
let city = user && user.address && user.address.city;

// With optional chaining (ES2020)
let city2 = user?.address?.city; // undefined (no error)

// Real examples
let user1 = {
  name: "John",
  address: {
    city: "New York",
  },
};

console.log(user1?.address?.city); // 'New York'
console.log(user1?.address?.zipCode); // undefined
console.log(user1?.contact?.phone); // undefined

// With arrays
let users = null;
console.log(users?.[0]?.name); // undefined

let users2 = [{ name: "John" }, { name: "Jane" }];
console.log(users2?.[0]?.name); // 'John'

// With functions
let obj = null;
console.log(obj?.someMethod?.()); // undefined (doesn't call if method doesn't exist)

let obj2 = {
  greet: function () {
    return "Hello";
  },
};
console.log(obj2?.greet?.()); // 'Hello'

Spread Operator (...)

Expands iterables (arrays, objects) into individual elements.

// Array spread
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

// Copy array
let original = [1, 2, 3];
let copy = [...original]; // [1, 2, 3]
copy.push(4);
console.log(original); // [1, 2, 3] (unchanged)
console.log(copy); // [1, 2, 3, 4]

// Object spread
let obj1 = { name: "John", age: 25 };
let obj2 = { city: "New York", country: "USA" };
let merged = { ...obj1, ...obj2 };
// { name: 'John', age: 25, city: 'New York', country: 'USA' }

// Copy object
let person = { name: "John" };
let personCopy = { ...person };

// Function arguments
function sum(a, b, c) {
  return a + b + c;
}
let numbers = [1, 2, 3];
console.log(sum(...numbers)); // 6

Comma Operator (,)

Evaluates multiple expressions, returns the last one.

// Basic usage
let x = (1, 2, 3, 4, 5); // x = 5 (returns last value)
console.log(x); // 5

// In for loop
for (let i = 0, j = 10; i < 5; i++, j--) {
  console.log(i, j);
}
// Output: 0 10, 1 9, 2 8, 3 7, 4 6

// Multiple assignments
let a, b, c;
a = ((b = 1), (c = 2), 3); // a = 3, b = 1, c = 2

// Rarely used in practice

delete Operator

Removes a property from an object.

let person = {
  name: "John",
  age: 25,
  city: "New York",
};

delete person.age;
console.log(person); // { name: 'John', city: 'New York' }

// Returns true if successful
console.log(delete person.city); // true
console.log(person); // { name: 'John' }

// Cannot delete non-configurable properties
let obj = {};
Object.defineProperty(obj, "prop", {
  value: 42,
  configurable: false,
});
console.log(delete obj.prop); // false (cannot delete)

// Cannot delete variables
let x = 10;
console.log(delete x); // false

void Operator

Evaluates an expression and returns undefined.

// Basic usage
console.log(void 0); // undefined
console.log(void "hello"); // undefined
console.log(void 2 + 3); // undefined (void 2 is undefined, undefined + 3 is NaN)

// Used to get undefined reliably
let x = void 0; // x = undefined

// Prevent default in links (old way)
// <a href="javascript:void(0)">Click</a>

// IIFE (Immediately Invoked Function Expression)
void (function () {
  console.log("IIFE executed");
})();

Practical Examples

Example 1: Calculate Discount

let price = 100;
let discount = 0.2; // 20%
let finalPrice = price - price * discount;
console.log(finalPrice); // 80

// Alternative
let finalPrice2 = price * (1 - discount);
console.log(finalPrice2); // 80

// With ternary
let isMember = true;
let memberDiscount = isMember ? 0.2 : 0;
let finalPrice3 = price * (1 - memberDiscount);
console.log(finalPrice3); // 80

Example 2: Check Eligibility

let age = 25;
let hasID = true;
let canEnter = age >= 18 && hasID;
console.log(canEnter); // true

// With additional checks
let isVIP = false;
let hasTicket = true;
let canEnterVIP = (age >= 21 && hasID && hasTicket) || isVIP;
console.log(canEnterVIP); // true

Example 3: Default Values

// Using ||
let userInput = "";
let value = userInput || "Default";
console.log(value); // 'Default'

// Problem with ||
let count = 0;
let value2 = count || 10;
console.log(value2); // 10 (but 0 is valid!)

// Solution: Use ??
let count2 = 0;
let value3 = count2 ?? 10;
console.log(value3); // 0 (correct!)

Example 4: Conditional Message

let score = 85;
let message = score >= 60 ? "Pass" : "Fail";
console.log(message); // 'Pass'

// With grade
let grade =
  score >= 90
    ? "A"
    : score >= 80
      ? "B"
      : score >= 70
        ? "C"
        : score >= 60
          ? "D"
          : "F";
console.log(grade); // 'B'

Example 5: Safe Property Access

// Without optional chaining
let user = { name: "John" };
let city = user && user.address && user.address.city;
console.log(city); // undefined

// With optional chaining
let city2 = user?.address?.city;
console.log(city2); // undefined

// Real use case
function getUserCity(user) {
  return user?.address?.city ?? "Unknown";
}

console.log(getUserCity({ name: "John" })); // 'Unknown'
console.log(getUserCity({ name: "Jane", address: { city: "NY" } })); // 'NY'

Example 6: Complex Expression Evaluation

let a = 5;
let b = 10;
let c = 15;

// Complex expression
let result = a + b * c - (a++ + ++b) / --c;

// Break it down:
// 1. b * c = 10 * 15 = 150
// 2. a++ returns 5, a becomes 6
// 3. ++b makes b = 11, returns 11
// 4. 5 + 11 = 16
// 5. --c makes c = 14, returns 14
// 6. 16 / 14 ≈ 1.14
// 7. a + 150 - 1.14 = 6 + 150 - 1.14 = 154.86

console.log(result); // 154.85714285714286
console.log(a, b, c); // 6 11 14

Interview Questions & Answers

Q1: What's the difference between == and ===?

Answer:

Feature== (Loose Equality)=== (Strict Equality)
Type coercionYesNo
ComparesValues only (after coercion)Values AND types
5 == '5'truefalse
0 == falsetruefalse
null == undefinedtruefalse
Best practiceAvoid (except null check)Always use

Example:

// == converts types
console.log(5 == "5"); // true (string converted to number)
console.log(0 == false); // true (false converted to 0)
console.log("" == 0); // true (both converted to 0)

// === does NOT convert types
console.log(5 === "5"); // false (different types)
console.log(0 === false); // false (different types)
console.log("" === 0); // false (different types)

// Only acceptable use of ==
if (value == null) {
  // Checks both null AND undefined
  console.log("No value");
}

Q2: Explain short-circuit evaluation in logical operators.

Answer:

Short-circuit evaluation means logical operators stop evaluating as soon as the result is determined.

AND (&&):

  • Stops at first falsy value
  • Returns first falsy OR last value
// Stops at false
console.log(false && "hello"); // false (doesn't evaluate 'hello')
console.log(null && "world"); // null (stops at null)

// Evaluates all if all truthy
console.log(true && "hello"); // 'hello' (returns last value)
console.log(5 && "world"); // 'world'

// Practical use
let user = { name: "John" };
user && console.log(user.name); // 'John' (safe access)

let noUser = null;
noUser && console.log(noUser.name); // null (prevents error)

OR (||):

  • Stops at first truthy value
  • Returns first truthy OR last value
// Stops at true
console.log(true || "hello"); // true (doesn't evaluate 'hello')
console.log(5 || "world"); // 5 (stops at 5)

// Evaluates all if all falsy
console.log(false || "hello"); // 'hello' (returns last value)
console.log(0 || null); // null (last value)

// Practical use: Default values
let userName = "";
let name = userName || "Guest"; // 'Guest'

let config = null;
let settings = config || { theme: "light" }; // default object

Why it matters:

  • Performance: Avoids unnecessary evaluations
  • Safety: Prevents errors with null/undefined
  • Concise code: Replace if statements

Q3: What is the difference between ++x and x++?

Answer:

Feature++x (Pre-increment)x++ (Post-increment)
When changesBefore expressionAfter expression
ReturnsNew valueOld value
Examplelet y = ++x → y gets new xlet y = x++ → y gets old x

Examples:

// Post-increment (x++)
let a = 5;
console.log(a++); // 5 (returns old value)
console.log(a); // 6 (now incremented)

// Pre-increment (++x)
let b = 5;
console.log(++b); // 6 (increments first, returns new value)
console.log(b); // 6

// In expressions
let x = 5;
let y = x++ + x; // 5 + 6 = 11
console.log(y); // 11
console.log(x); // 6

let m = 5;
let n = ++m + m; // 6 + 6 = 12
console.log(n); // 12
console.log(m); // 6

Complex Example:

let a = 5;
let b = a++ + ++a; // What is b?

// Step by step:
// 1. a++ returns 5, then a becomes 6
// 2. ++a makes a = 7, returns 7
// 3. b = 5 + 7 = 12

console.log(a); // 7
console.log(b); // 12

Q4: Explain operator precedence with an example.

Answer:

Operator precedence determines the order of operations when multiple operators are used.

Precedence levels (high to low):

  1. Grouping: ()
  2. Member access: . []
  3. Increment/Decrement: ++ --
  4. Exponentiation: **
  5. Multiplicative: * / %
  6. Additive: + -
  7. Comparison: < > <= >=
  8. Equality: == ===
  9. Logical AND: &&
  10. Logical OR: ||
  11. Ternary: ? :
  12. Assignment: = += etc.

Examples:

// Multiplication before addition
console.log(2 + 3 * 4); // 14 (not 20)
// 3 * 4 = 12, then 2 + 12 = 14

// Use parentheses to override
console.log((2 + 3) * 4); // 20
// (2 + 3) = 5, then 5 * 4 = 20

// Complex example
let result = 10 + 5 * 2 - 8 / 4;
// Step by step:
// 1. 5 * 2 = 10
// 2. 8 / 4 = 2
// 3. 10 + 10 - 2 = 18
console.log(result); // 18

// Logical operators
console.log(true || (false && false)); // true
// && has higher precedence than ||
// false && false = false
// true || false = true

// Always use parentheses for clarity!
console.log((true || false) && false); // false

Q5: What is the difference between || and ???

Answer:

Feature|| (OR)?? (Nullish Coalescing)
Returns right if left isAny falsy valueOnly null or undefined
Falsy valuesfalse, 0, '', null, undefined, NaN, -0Only null, undefined
Use caseGeneral defaultsPreserve 0, false, ''

Examples:

// || treats all falsy values as "no value"
console.log(0 || 10); // 10 (0 is falsy)
console.log(false || true); // true (false is falsy)
console.log("" || "default"); // 'default' ('' is falsy)
console.log(null || "default"); // 'default'
console.log(undefined || "default"); // 'default'

// ?? only treats null/undefined as "no value"
console.log(0 ?? 10); // 0 (0 is NOT null/undefined)
console.log(false ?? true); // false (false is NOT null/undefined)
console.log("" ?? "default"); // '' (empty string is NOT null/undefined)
console.log(null ?? "default"); // 'default'
console.log(undefined ?? "default"); // 'default'

// Real-world example
let userAge = 0; // 0 is a valid age

// Using || (wrong!)
let age1 = userAge || 18; // 18 (treats 0 as falsy)

// Using ?? (correct!)
let age2 = userAge ?? 18; // 0 (preserves 0)

// Function with default parameter
function greet(name) {
  name = name ?? "Guest"; // Better than ||
  console.log(`Hello, ${name}!`);
}

greet(""); // Hello, ! (empty string is valid)
greet(null); // Hello, Guest!
greet(undefined); // Hello, Guest!

Q6: What does the modulus operator (%) do?

Answer:

The modulus operator (%) returns the remainder after division.

// Basic examples
console.log(10 % 3); // 1 (10 ÷ 3 = 3 remainder 1)
console.log(15 % 4); // 3 (15 ÷ 4 = 3 remainder 3)
console.log(20 % 5); // 0 (20 ÷ 5 = 4 remainder 0)
console.log(7 % 2); // 1 (odd number)
console.log(8 % 2); // 0 (even number)

// Negative numbers
console.log(-10 % 3); // -1 (result has sign of dividend)
console.log(10 % -3); // 1

// Common use cases:

// 1. Check if even or odd
function isEven(num) {
  return num % 2 === 0;
}
console.log(isEven(4)); // true
console.log(isEven(5)); // false

// 2. Cycle through array indices
let colors = ["red", "green", "blue"];
for (let i = 0; i < 10; i++) {
  console.log(colors[i % colors.length]); // Loops through colors
}

// 3. Time calculations
let totalMinutes = 135;
let hours = Math.floor(totalMinutes / 60); // 2
let minutes = totalMinutes % 60; // 15
console.log(`${hours}h ${minutes}m`); // "2h 15m"

// 4. Fizz Buzz problem
for (let i = 1; i <= 15; i++) {
  if (i % 3 === 0 && i % 5 === 0) {
    console.log("FizzBuzz");
  } else if (i % 3 === 0) {
    console.log("Fizz");
  } else if (i % 5 === 0) {
    console.log("Buzz");
  } else {
    console.log(i);
  }
}

Q7: Explain the ternary operator with examples.

Answer:

The ternary operator is a shorthand for if-else statements.

Syntax:

condition ? valueIfTrue : valueIfFalse;

Examples:

// Basic usage
let age = 20;
let status = age >= 18 ? "Adult" : "Minor";
console.log(status); // 'Adult'

// Replacing if-else
// Before:
let message;
if (isLoggedIn) {
  message = "Welcome back!";
} else {
  message = "Please login";
}

// After:
let message = isLoggedIn ? "Welcome back!" : "Please login";

// In function returns
function getDiscount(isMember) {
  return isMember ? 0.2 : 0;
}

// Nested ternary (use sparingly!)
let score = 85;
let grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";

// Multiple conditions
let price = 100;
let discount = price > 50 ? (price > 100 ? 0.2 : 0.1) : 0;

// With function calls
let result = isValid ? processData() : showError();

// Common use case: Default values
let userName = input ? input : "Guest";
// Or better:
let userName = input || "Guest";
let userName = input ?? "Guest"; // If you want to preserve false/0/''

When to use:

  • ✅ Simple conditions
  • ✅ Assignments based on condition
  • ✅ Return statements
  • ❌ Complex logic (use if-else instead)
  • ❌ Multiple nested conditions (hard to read)

Q8: What is the difference between typeof and instanceof?

Answer:

Featuretypeofinstanceof
ReturnsStringBoolean
ChecksPrimitive typeObject constructor/class
Works onAll valuesObjects only
Syntaxtypeof valuevalue instanceof Constructor

typeof:

// Checks primitive types
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' (bug!)
console.log(typeof Symbol()); // 'symbol'
console.log(typeof 123n); // 'bigint'

// For objects
console.log(typeof {}); // 'object'
console.log(typeof []); // 'object' (can't distinguish arrays!)
console.log(typeof function () {}); // 'function'

instanceof:

// Checks object constructor/class
let arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true (arrays are objects)

let date = new Date();
console.log(date instanceof Date); // true
console.log(date instanceof Object); // true

// Custom constructor
function Person(name) {
  this.name = name;
}
let john = new Person("John");
console.log(john instanceof Person); // true
console.log(john instanceof Object); // true

// Doesn't work on primitives
console.log(5 instanceof Number); // false
console.log("hello" instanceof String); // false

When to use:

  • typeof: Check primitive types (number, string, boolean, etc.)
  • instanceof: Check if object is instance of specific class/constructor
  • Array.isArray(): Specifically check for arrays (better than typeof)

Q9: How do you check if a value is NaN?

Answer:

NaN (Not a Number) is a special numeric value that represents an invalid number operation.

The Problem:

console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
console.log(typeof NaN); // 'number' (yes, NaN is a number type!)

// Even comparing NaN to itself returns false!
let x = NaN;
console.log(x == NaN); // false
console.log(x === NaN); // false

Solutions:

// 1. isNaN() function (be careful!)
console.log(isNaN(NaN)); // true
console.log(isNaN(123)); // false
console.log(isNaN("hello")); // true (converts to NaN)
console.log(isNaN("123")); // false (converts to 123)
console.log(isNaN(undefined)); // true (converts to NaN)

// Problem: isNaN() converts non-numbers to numbers first!
console.log(isNaN("hello")); // true (but 'hello' is not NaN, it's a string!)

// 2. Number.isNaN() - RECOMMENDED (ES6+)
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(123)); // false
console.log(Number.isNaN("hello")); // false (no conversion!)
console.log(Number.isNaN("123")); // false
console.log(Number.isNaN(undefined)); // false

// 3. Self-comparison trick
function isReallyNaN(value) {
  return value !== value; // Only NaN is not equal to itself
}
console.log(isReallyNaN(NaN)); // true
console.log(isReallyNaN(123)); // false

// 4. Object.is() method
console.log(Object.is(NaN, NaN)); // true
console.log(Object.is(5, NaN)); // false

Best Practice:

// ✅ Use Number.isNaN() for strict NaN checking
if (Number.isNaN(value)) {
  console.log("Value is NaN");
}

// ❌ Avoid isNaN() unless you want type coercion
if (isNaN(value)) {
  // This will be true for non-numeric strings too!
}

How NaN is created:

console.log(0 / 0); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log(parseInt("hello")); // NaN
console.log("hello" * 5); // NaN
console.log(undefined + 1); // NaN
console.log(Number("abc")); // NaN

Q10: What happens when you use the + operator with different types?

Answer:

The + operator behaves differently based on operand types:

String Concatenation (if any operand is a string):

// String + anything = String (concatenation)
console.log("5" + 5); // '55'
console.log(5 + "5"); // '55'
console.log("Hello" + " World"); // 'Hello World'
console.log("5" + true); // '5true'
console.log("Value: " + null); // 'Value: null'

// Order matters!
console.log(5 + 5 + "5"); // '105' (5+5=10, then '10'+'5'='105')
console.log("5" + 5 + 5); // '555' ('5'+'5'='55', then '55'+5='555')
console.log("5" + (5 + 5)); // '510' (parentheses force 5+5 first)

Numeric Addition (if both operands are numbers):

// Number + Number = Number (addition)
console.log(5 + 5); // 10
console.log(3.14 + 2.86); // 6
console.log(-5 + 10); // 5

// Boolean to Number conversion
console.log(true + true); // 2 (true = 1)
console.log(true + false); // 1 (true=1, false=0)
console.log(5 + true); // 6 (5 + 1)

Type Coercion Rules:

ExpressionResultExplanation
5 + 510Both numbers → addition
'5' + 5'55'String present → concatenation
5 + '5''55'String present → concatenation
5 + 5 + '5''105'Left-to-right: 5+5=10, then '10'+'5'
'5' + 5 + 5'555'Left-to-right: '5'+'5', then +'5'
true + 12true → 1, then 1+1
false + 55false → 0, then 0+5
'5' + null'5null'null → 'null' (string concat)
5 + null5null → 0, then 5+0
'5' + undefined'5undefined'undefined → 'undefined' (concat)
5 + undefinedNaNundefined → NaN, then 5+NaN

Common Pitfalls:

// Unexpected string concatenation
let total = "10" + 5; // '105' (not 15!)

// Fix: Convert to number first
let total = Number("10") + 5; // 15
let total = +"10" + 5; // 15 (unary plus)
let total = parseInt("10") + 5; // 15

// Array concatenation (weird!)
console.log([1, 2] + [3, 4]); // '1,23,4' (both convert to strings)
console.log([] + []); // '' (empty string)
console.log([] + {}); // '[object Object]'
console.log({} + []); // '[object Object]' (in some contexts)

Best Practices:

// ✅ Be explicit with types
let sum = Number(str1) + Number(str2);

// ✅ Use template literals for string building
let message = `Total: ${num1 + num2}`;

// ✅ Avoid mixing types
let total = parseFloat(price) + tax; // Both numbers

// ❌ Avoid relying on implicit coercion
let result = userInput + 10; // Dangerous if userInput is string!

Q11: Explain operator associativity with examples.

Answer:

Associativity determines the direction in which operators of the same precedence are evaluated.

Types:

  • Left-to-right: Most operators (+, -, *, /, %)
  • Right-to-left: Assignment (=), Exponentiation (**)

Left-to-right (Addition, Subtraction):

// Evaluated from left to right
let result = 10 - 5 - 2;
// (10 - 5) - 2 = 5 - 2 = 3
console.log(result); // 3

let result2 = 100 / 10 / 2;
// (100 / 10) / 2 = 10 / 2 = 5
console.log(result2); // 5

let result3 = 5 + 3 + 2;
// (5 + 3) + 2 = 8 + 2 = 10
console.log(result3); // 10

Right-to-left (Assignment):

// Evaluated from right to left
let a, b, c;
a = b = c = 5;
// Equivalent to: a = (b = (c = 5))
// c = 5, then b = c, then a = b
console.log(a, b, c); // 5 5 5

// Chain assignment
let x = (y = 10);
// y = 10 first, then x = y
console.log(x, y); // 10 10

Right-to-left (Exponentiation):

// Exponentiation is right-to-left
console.log(2 ** (3 ** 2));
// 2 ** (3 ** 2) = 2 ** 9 = 512
console.log(2 ** (3 ** 2)); // 512

// Compare with left-to-right
console.log((2 ** 3) ** 2);
// (2 ** 3) ** 2 = 8 ** 2 = 64
console.log((2 ** 3) ** 2); // 64

Mixed Associativity:

// Assignment with operations
let x = 5;
x += x *= 2;
// Right-to-left for assignment
// x *= 2 → x = 5 * 2 = 10
// x += 10 → x = 10 + 10 = 20
console.log(x); // 20

// Complex example
let a = 1,
  b = 2,
  c = 3;
a += b -= c;
// b -= c → b = 2 - 3 = -1
// a += b → a = 1 + (-1) = 0
console.log(a, b, c); // 0 -1 3

Q12: What is optional chaining and when should you use it?

Answer:

Optional chaining (?.) allows safe access to nested properties without checking each level for null or undefined.

Without Optional Chaining (Old Way):

let user = null;

// Traditional check (verbose)
let city;
if (user && user.address && user.address.city) {
  city = user.address.city;
}

// Ternary (still verbose)
let city = user ? (user.address ? user.address.city : undefined) : undefined;

// Logical AND (still long)
let city = user && user.address && user.address.city;

With Optional Chaining (ES2020):

let user = null;
let city = user?.address?.city; // undefined (no error!)

// Real examples
let user1 = {
  name: "John",
  address: {
    city: "New York",
    zip: "10001",
  },
};

console.log(user1?.address?.city); // 'New York'
console.log(user1?.address?.country); // undefined (doesn't exist)
console.log(user1?.contact?.phone); // undefined (contact doesn't exist)

With Arrays:

let users = null;
console.log(users?.[0]); // undefined (no error!)

let users2 = [{ name: "John" }, { name: "Jane" }];
console.log(users2?.[0]?.name); // 'John'
console.log(users2?.[5]?.name); // undefined (index 5 doesn't exist)

With Functions:

let obj = null;
console.log(obj?.someMethod?.()); // undefined (no error!)

let obj2 = {
  greet: function () {
    return "Hello";
  },
};
console.log(obj2?.greet?.()); // 'Hello'
console.log(obj2?.goodbye?.()); // undefined (method doesn't exist)

// With arguments
let user = {
  update: function (data) {
    console.log("Updating:", data);
  },
};
user?.update?.({ name: "John" }); // Logs: Updating: { name: 'John' }

Common Use Cases:

// 1. API responses
let response = await fetch("/api/user");
let data = await response.json();
let userName = data?.user?.profile?.name ?? "Unknown";

// 2. DOM manipulation
let element = document.querySelector("#myElement");
let text = element?.textContent?.trim();

// 3. Event handlers
button?.addEventListener("click", handler);

// 4. Configuration objects
let config = getConfig();
let theme = config?.ui?.theme ?? "light";

// 5. Deeply nested data
let company = {
  employees: [
    {
      personal: {
        address: {
          city: "NYC",
        },
      },
    },
  ],
};
let city = company?.employees?.[0]?.personal?.address?.city; // 'NYC'

Combining with Nullish Coalescing:

// Safe access with default value
let user = null;
let userName = user?.profile?.name ?? "Guest";
console.log(userName); // 'Guest'

// Multiple levels
let app = {};
let theme = app?.settings?.ui?.theme ?? "dark";
console.log(theme); // 'dark'

When NOT to use:

// ❌ Don't use for guaranteed properties
let user = { name: "John" }; // name always exists
let name = user?.name; // Unnecessary

// ✅ Use for optional/uncertain properties
let city = user?.address?.city; // address might not exist

Q13: What are the differences between bitwise operators and logical operators?

Answer:

Logical Operators work with boolean values:

// Logical operators return boolean or original value
console.log(true && false); // false
console.log(true || false); // true
console.log(!true); // false

// Work with truthy/falsy values
console.log(5 && 10); // 10 (last truthy value)
console.log(0 || 5); // 5 (first truthy value)

Bitwise Operators work with binary representations of numbers:

// Bitwise AND (&)
console.log(5 & 3); // 1
// Binary: 5 = 101, 3 = 011
//         101
//       & 011
//       = 001 (1)

// Bitwise OR (|)
console.log(5 | 3); // 7
// Binary: 5 = 101, 3 = 011
//         101
//       | 011
//       = 111 (7)

// Bitwise XOR (^)
console.log(5 ^ 3); // 6
// Binary: 5 = 101, 3 = 011
//         101
//       ^ 011
//       = 110 (6)

// Bitwise NOT (~)
console.log(~5); // -6
// Binary: 5 = 00000101
//        ~5 = 11111010 (two's complement = -6)

// Left Shift (<<)
console.log(5 << 1); // 10
// Binary: 5 = 101
//     5<<1 = 1010 (10) - shifts left, adds 0

// Right Shift (>>)
console.log(5 >> 1); // 2
// Binary: 5 = 101
//     5>>1 = 10 (2) - shifts right, removes last bit

Key Differences:

FeatureLogical (&&, `, !`)Bitwise (&, `, ^, ~`)
Operates onBoolean valuesBinary bits
ReturnsBoolean or original valueNumber
Use caseConditions, control flowBit manipulation, flags
Short-circuitYes (&&, ``)No

Common Pitfalls:

// ❌ Using & instead of &&
if ((age > 18) & hasLicense) {
  // Wrong! & is bitwise, not logical
}

// ✅ Correct
if (age > 18 && hasLicense) {
  // Correct!
}

// Bitwise returns numbers, not booleans
console.log(true & true); // 1 (not true)
console.log(true && true); // true

Practical Bitwise Use Cases:

// 1. Check if number is even (faster than %)
function isEven(num) {
  return (num & 1) === 0;
}
console.log(isEven(4)); // true
console.log(isEven(5)); // false

// 2. Swap without temporary variable
let a = 5,
  b = 3;
a = a ^ b;
b = a ^ b; // b = (a^b)^b = a
a = a ^ b; // a = (a^b)^a = b
console.log(a, b); // 3 5

// 3. Toggle boolean (XOR)
let flag = 1;
flag = flag ^ 1; // Toggle: 1^1=0
console.log(flag); // 0
flag = flag ^ 1; // Toggle: 0^1=1
console.log(flag); // 1

// 4. Permissions/flags
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)

Q14: How do compound assignment operators work?

Answer:

Compound assignment operators combine an operation with assignment.

Syntax: variable operator= value
Equivalent to: variable = variable operator value

All Compound Operators:

let x = 10;

// Addition
x += 5; // x = x + 5 = 15
console.log(x); // 15

// Subtraction
x -= 3; // x = x - 3 = 12
console.log(x); // 12

// Multiplication
x *= 2; // x = x * 2 = 24
console.log(x); // 24

// Division
x /= 4; // x = x / 4 = 6
console.log(x); // 6

// Modulus
x %= 4; // x = x % 4 = 2
console.log(x); // 2

// Exponentiation
x **= 3; // x = x ** 3 = 8
console.log(x); // 8

With Strings:

let greeting = "Hello";
greeting += " "; // greeting = greeting + " "
greeting += "World"; // greeting = greeting + "World"
console.log(greeting); // 'Hello World'

// Shorter version
let message = "Hi";
message += " there!";
console.log(message); // 'Hi there!'

Important Points:

// 1. Left side must be a variable
// x + y += 5; // ❌ Error: Invalid left-hand side
let x = 10;
x += 5; // ✅ Correct

// 2. Evaluation order matters
let a = 5;
a += a * 2; // a = 5 + (5 * 2) = 5 + 10 = 15
console.log(a); // 15

// 3. Works with any expression on right
let sum = 10;
sum += calculateTax(100); // sum = sum + calculateTax(100)

// 4. Can be chained (right-to-left)
let x = 5;
let y = 10;
x += y += 2; // y = 10 + 2 = 12, then x = 5 + 12 = 17
console.log(x, y); // 17 12

Practical Examples:

// Counter
let count = 0;
count += 1; // Increment
count -= 1; // Decrement

// Accumulator
let total = 0;
for (let i = 1; i <= 5; i++) {
  total += i; // total = total + i
}
console.log(total); // 15

// String builder
let html = "<div>";
html += "<h1>Title</h1>";
html += "<p>Content</p>";
html += "</div>";

// Price calculation
let price = 100;
price *= 1.1; // Add 10% tax
price -= 5; // Subtract $5 discount
console.log(price); // 105

Comparison with Regular Assignment:

// Compound (shorter)
x += 5;

// Regular (longer)
x = x + 5;

// Both equivalent, but compound is:
// ✅ More concise
// ✅ Clearer intent
// ✅ Less prone to typos (x vs y)

// Example of typo with regular assignment
let count = 10;
count = cont + 1; // ❌ Typo: 'cont' instead of 'count'

// Compound prevents this
count += 1; // ✅ Can't typo the variable

Q15: What is type coercion and how does it affect operators?

Answer:

Type coercion is automatic type conversion performed by JavaScript when operators are used with different types.

Implicit Coercion Examples:

// String coercion (+ operator with string)
console.log("5" + 3); // '53' (number to string)
console.log("Hello" + true); // 'Hellotrue' (boolean to string)
console.log("Age: " + null); // 'Age: null' (null to string)

// Number coercion (arithmetic operators)
console.log("5" - 3); // 2 (string to number)
console.log("10" * "2"); // 20 (both to numbers)
console.log("20" / "4"); // 5
console.log("10" % 3); // 1

// Boolean coercion (logical context)
if ("hello") {
  console.log("Truthy"); // Runs
}
if (0) {
  console.log("Won't run"); // Falsy
}

// Comparison coercion
console.log("5" == 5); // true (string to number)
console.log(false == 0); // true (boolean to number)
console.log(null == undefined); // true (special case)

How Different Operators Coerce:

| Operator | Preferred Type | Example | Result | | --------------- | ------------------------- | ----------- | ------- | -------------- | --- | | + | String (if one is string) | '5' + 3 | '53' | | - * / % | Number | '5' - 3 | 2 | | == | Varies | '5' == 5 | true | | === | No coercion | '5' === 5 | false | | && | | | Boolean | 'hello' && 0 | 0 | | ! | Boolean | !'hello' | false |

Conversion Rules:

// To String
String(123); // '123'
String(true); // 'true'
String(null); // 'null'
String(undefined); // 'undefined'
String([1, 2]); // '1,2'
String({ a: 1 }); // '[object Object]'

// To Number
Number("123"); // 123
Number("12.5"); // 12.5
Number(""); // 0
Number(" "); // 0
Number("hello"); // NaN
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN
Number([1]); // 1
Number([1, 2]); // NaN
Number({}); // NaN

// To Boolean
Boolean(1); // true (any non-zero number)
Boolean(0); // false
Boolean(""); // false
Boolean("hello"); // true (any non-empty string)
Boolean(null); // false
Boolean(undefined); // false
Boolean({}); // true (any object)
Boolean([]); // true (any array)

Common Pitfalls:

// Unexpected concatenation
let result = "10" + 5 + 5; // '1055' (not 20)
// Fix: Convert to number first
let result = Number("10") + 5 + 5; // 20

// Order matters!
console.log(1 + 2 + "3"); // '33' (1+2=3, then '3'+'3'='33')
console.log("1" + 2 + 3); // '123' ('1'+'2'='12', '12'+'3'='123')

// Boolean arithmetic
console.log(true + true); // 2 (1 + 1)
console.log(false + 1); // 1 (0 + 1)
console.log(true * 2); // 2 (1 * 2)

// Array/Object coercion
console.log([1] + [2]); // '12' (both convert to strings)
console.log({} + []); // '[object Object]' or 0 (context-dependent!)
console.log([] + {}); // '[object Object]'

Best Practices to Avoid Coercion Issues:

// ✅ Explicit conversion
let num = Number(userInput);
let str = String(value);
let bool = Boolean(value);

// ✅ Use === instead of ==
if (value === 5) {
  /* strict comparison */
}

// ✅ Parse numbers properly
let price = parseFloat("19.99");
let quantity = parseInt("5");

// ✅ Type checking before operations
function add(a, b) {
  if (typeof a !== "number" || typeof b !== "number") {
    throw new Error("Both arguments must be numbers");
  }
  return a + b;
}

// ✅ Use TypeScript for type safety
function multiply(a: number, b: number): number {
  return a * b;
}

Interview Question: "What is [] + {} in JavaScript?"

Answer:

console.log([] + {}); // '[object Object]'

// Explanation:
// 1. Both [] and {} are converted to strings
// 2. [] converts to '' (empty string)
// 3. {} converts to '[object Object]'
// 4. '' + '[object Object]' = '[object Object]'

// But:
console.log({} + []); // 0 or '[object Object]' (depends on context!)
// In statement context: {} is empty block, +[] converts to 0
// In expression context: '[object Object]'

Last updated on July 15, 2026

On this page

Operators - Performing Operations on DataWhat are Operators?Operator ClassificationTypes of Operators - Quick Reference1. Arithmetic OperatorsBasic ArithmeticArithmetic Operators TableIncrement & Decrement OperatorsComparison: Pre vs Post IncrementUnary Plus and MinusSpecial Cases2. Assignment OperatorsAssignment Operators TableBasic AssignmentCompound AssignmentChained AssignmentDestructuring Assignment3. Comparison OperatorsComparison Operators Table== vs === (Critical Interview Topic!)Detailed Comparison Table: == vs ===Greater/Less Than ComparisonsSpecial Comparison Cases4. Logical OperatorsLogical Operators TableAND Operator (&&)OR Operator (||)NOT Operator (!)Nullish Coalescing Operator (??)Short-Circuit Evaluation (Interview Topic!)Truth TableLogical Operator Precedence5. String OperatorsConcatenation (+)String Concatenation RulesTemplate Literals (Modern Way)6. Ternary Operator (Conditional)SyntaxBasic ExamplesNested Ternary (Use Sparingly!)Practical Use CasesTernary vs If-Else7. Type Operatorstypeof Operatortypeof Return Values Tableinstanceof Operatorin OperatorType Checking Best Practices8. Operator PrecedencePrecedence Table (High to Low)ExamplesComplex ExampleAssociativity ExamplesPrecedence Best Practices9. Special OperatorsOptional Chaining (?.)Spread Operator (...)Comma Operator (,)delete Operatorvoid OperatorPractical ExamplesExample 1: Calculate DiscountExample 2: Check EligibilityExample 3: Default ValuesExample 4: Conditional MessageExample 5: Safe Property AccessExample 6: Complex Expression EvaluationInterview Questions & AnswersQ1: What's the difference between == and ===?Q2: Explain short-circuit evaluation in logical operators.Q3: What is the difference between ++x and x++?Q4: Explain operator precedence with an example.Q5: What is the difference between || and ???Q6: What does the modulus operator (%) do?Q7: Explain the ternary operator with examples.Q8: What is the difference between typeof and instanceof?Q9: How do you check if a value is NaN?Q10: What happens when you use the + operator with different types?Q11: Explain operator associativity with examples.Q12: What is optional chaining and when should you use it?Q13: What are the differences between bitwise operators and logical operators?Q14: How do compound assignment operators work?Q15: What is type coercion and how does it affect operators?