0% found this document useful (0 votes)
6 views60 pages

Python Code Interview

This document is a comprehensive cheat sheet for Python interview preparation, covering essential topics such as Big O notation, data types, control flow, data structures, functions, classes, exception handling, modules, algorithms, and interview tips. It includes code examples for various time complexities and common algorithms, as well as best practices for coding interviews. The document emphasizes the importance of understanding concepts deeply and practicing consistently for interview success.

Uploaded by

iansheezy1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views60 pages

Python Code Interview

This document is a comprehensive cheat sheet for Python interview preparation, covering essential topics such as Big O notation, data types, control flow, data structures, functions, classes, exception handling, modules, algorithms, and interview tips. It includes code examples for various time complexities and common algorithms, as well as best practices for coding interviews. The document emphasizes the importance of understanding concepts deeply and practicing consistently for interview success.

Uploaded by

iansheezy1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 60

Python Code

🐍 Python Interview Prep Cheat Sheet


The ultimate guide to ace your Python interviews

📊 Big O Notation - Time & Space Complexity


Notation Name Example Description

O(1) Constant arr[0] Same time regardless of input


size

O(log n) Logarithmic Binary search Reduces problem by half each


step

O(n) Linear for i in arr Time grows linearly with input

O(n log n) Linearithmic Merge sort Efficient sorting algorithms

O(n²) Quadratic Nested loops Compare every pair

O(2ⁿ) Exponential Fibonacci (naive) Avoid this!


# O(1) - Constant
def get_first(arr):
return arr[0] if arr else None

# O(n) - Linear
def find_max(arr):
max_val = arr[0]
for num in arr: # visits each element once
if num > max_val:
max_val = num
return max_val

# O(n²) - Quadratic
def bubble_sort(arr):
for i in range(len(arr)):
for j in range(len(arr) - 1): # nested loop = O(n²)
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]

🔢 Data Types & Variables


# Primitive Types
integer = 42
float_num = 3.14
string = "Hello World"
boolean = True
none_type = None

# Type checking
print(type(42)) # <class 'int'>
print(isinstance(42, int)) # True

# String operations (Important for interviews!)


s = "python"
print(s[0]) # 'p' - indexing
print(s[-1]) # 'n' - negative indexing
print(s[1:4]) # 'yth' - slicing
print(s[::-1]) # 'nohtyp' - reverse
print(len(s)) # 6 - length

🔄 Control Flow
Conditional Statements
# if-elif-else
score = 85
if score >= 90:
grade = 'A'
elif score >= 80:
grade = 'B'
else:
grade = 'C'

# Ternary operator
result = "Pass" if score >= 60 else "Fail"
# Multiple conditions
if score >= 80 and attendance >= 75:
print("Eligible for honors")

Loops
# For loops
for i in range(5): # 0, 1, 2, 3, 4
print(i)

for i in range(2, 8, 2): # 2, 4, 6 (start, stop, step)


print(i)

# While loops
count = 0
while count < 5:
print(count)
count += 1

# Loop control
for i in range(10):
if i == 3:
continue # skip this iteration
if i == 7:
break # exit loop
print(i)

📋 Data Structures
Lists (Dynamic Arrays)
# Creation and basic operations - O(1) append, O(n) insert
arr = [1, 2, 3]
arr.append(4) # [1, 2, 3, 4] - O(1)
arr.insert(0, 0) # [0, 1, 2, 3, 4] - O(n)
arr.remove(2) # [0, 1, 3, 4] - O(n)
popped = arr.pop() # returns 4, arr = [0, 1, 3] - O(1)

# List comprehension (Very common in interviews!)


squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
evens = [x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8]
Dictionaries (Hash Maps)
# Creation - Average O(1) for get/set
person = {"name": "Alice", "age": 30}
person["city"] = "NYC" # Add key-value pair

# Dictionary methods
print(person.get("age", 0)) # 30 (with default)
print(person.keys()) # dict_keys(['name', 'age', 'city'])
print(person.values()) # dict_values(['Alice', 30, 'NYC'])
print(person.items()) # dict_items([('name', 'Alice'), ...])

# Dictionary comprehension
word_lengths = {word: len(word) for word in ["python", "java", "go"]}

Sets
# Unique elements, O(1) average for add/remove/lookup
unique_nums = {1, 2, 3, 3, 4} # {1, 2, 3, 4}
unique_nums.add(5)
unique_nums.remove(1)

# Set operations
set1 = {1, 2, 3}
set2 = {3, 4, 5}
print(set1 & set2) # {3} - intersection
print(set1 | set2) # {1, 2, 3, 4, 5} - union
print(set1 - set2) # {1, 2} - difference

Tuples
# Immutable sequences
coordinates = (10, 20)
x, y = coordinates # tuple unpacking
print(x) # 10

# Named tuples (for cleaner code)


from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x) # 10
🔧 Functions
# Basic function
def greet(name, greeting="Hello"):
"""Function with default parameter"""
return f"{greeting}, {name}!"

# Variable arguments
def sum_all(*args):
return sum(args)

def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")

# Lambda functions (anonymous functions)


square = lambda x: x**2
numbers = [1, 2, 3, 4, 5]
squared = list(map(square, numbers)) # [1, 4, 9, 16, 25]

# Higher-order functions
filtered = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]

🏗️ Classes & Objects


class Person:
# Class variable
species = "Homo sapiens"

def __init__(self, name, age):


# Instance variables
self.name = name
self.age = age

def introduce(self):
return f"Hi, I'm {self.name} and I'm {self.age} years old"

def __str__(self):
return f"Person(name={self.name}, age={self.age})"

def __repr__(self):
return f"Person('{self.name}', {self.age})"
# Inheritance
class Student(Person):
def __init__(self, name, age, student_id):
super().__init__(name, age) # Call parent constructor
self.student_id = student_id

def study(self):
return f"{self.name} is studying"

# Usage
alice = Person("Alice", 25)
bob = Student("Bob", 20, "S12345")

⚠️ Exception Handling
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
else:
print("No errors occurred")
finally:
print("This always runs")

# Custom exceptions
class CustomError(Exception):
def __init__(self, message):
self.message = message
super().__init__(self.message)

def validate_age(age):
if age < 0:
raise CustomError("Age cannot be negative")
return age

📦 Modules & Imports


# Different import styles
import math
from collections import deque, defaultdict
from datetime import datetime as dt
import numpy as np # aliasing

# Common built-in modules for interviews


from collections import Counter, defaultdict, deque
from itertools import combinations, permutations
from functools import lru_cache
import heapq
import bisect

# Example usage
counter = Counter("hello") # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})
dd = defaultdict(list) # default value is empty list
queue = deque([1, 2, 3]) # efficient append/pop from both ends

🧮 Essential Algorithms
Searching
# Binary Search - O(log n)
def binary_search(arr, target):
left, right = 0, len(arr) - 1

while left <= right:


mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1

return -1 # not found

Sorting
# Quick Sort - O(n log n) average, O(n²) worst
def quicksort(arr):
if len(arr) <= 1:
return arr

pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]

return quicksort(left) + middle + quicksort(right)

# Built-in sorting (Timsort - O(n log n))


arr.sort() # in-place
sorted_arr = sorted(arr) # returns new list

Two Pointers Technique


def two_sum_sorted(arr, target):
"""Find two numbers that sum to target in sorted array"""
left, right = 0, len(arr) - 1

while left < right:


current_sum = arr[left] + arr[right]
if current_sum == target:
return [left, right]
elif current_sum < target:
left += 1
else:
right -= 1

return []

🎯 Common Interview Patterns


Sliding Window
def max_sum_subarray(arr, k):
"""Maximum sum of subarray of size k"""
if len(arr) < k:
return 0

# Calculate sum of first window


window_sum = sum(arr[:k])
max_sum = window_sum
# Slide the window
for i in range(k, len(arr)):
window_sum = window_sum - arr[i - k] + arr[i]
max_sum = max(max_sum, window_sum)

return max_sum

Hash Map for Lookups


def two_sum(nums, target):
"""Find indices of two numbers that sum to target"""
seen = {}

for i, num in enumerate(nums):


complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = i

return []

Depth-First Search (DFS)


def dfs_recursive(graph, node, visited):
visited.add(node)
print(node)

for neighbor in graph[node]:


if neighbor not in visited:
dfs_recursive(graph, neighbor, visited)

def dfs_iterative(graph, start):


visited = set()
stack = [start]

while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
print(node)
stack.extend(graph[node])
🚀 Advanced Python Features
Decorators
def timer(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f} seconds")
return result
return wrapper

@timer
def slow_function():
time.sleep(1)
return "Done"

Generators
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b

# Usage
fib = fibonacci()
for _ in range(10):
print(next(fib)) # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

Context Managers
# File handling with automatic cleanup
with open('file.txt', 'r') as f:
content = f.read()
# File automatically closed

# Custom context manager


class Timer:
def __enter__(self):
self.start = time.time()
return self

def __exit__(self, *args):


print(f"Elapsed: {time.time() - self.start:.4f}s")

with Timer():
time.sleep(1)

💡 Interview Tips & Tricks


String Manipulation
# Common string operations
s = "Hello World"
print(s.lower()) # "hello world"
print(s.replace(" ", "_")) # "Hello_World"
print(s.split()) # ["Hello", "World"]
print("_".join(["a", "b", "c"])) # "a_b_c"

# Check if palindrome
def is_palindrome(s):
return s == s[::-1]

# Remove duplicates while preserving order


def remove_duplicates(lst):
seen = set()
result = []
for item in lst:
if item not in seen:
seen.add(item)
result.append(item)
return result

Memory Optimization
# Use generators for large datasets
def process_large_file(filename):
with open(filename, 'r') as f:
for line in f: # doesn't load entire file into memory
yield line.strip()
# Use slots for memory-efficient classes
class Point:
__slots__ = ['x', 'y'] # reduces memory overhead

def __init__(self, x, y):


self.x = x
self.y = y

🎯 Final Interview Checklist


Before coding:

●​ [ ] Understand the problem completely


●​ [ ] Ask clarifying questions
●​ [ ] Think about edge cases
●​ [ ] Discuss approach and time complexity

While coding:

●​ [ ] Write clean, readable code


●​ [ ] Use meaningful variable names
●​ [ ] Add comments for complex logic
●​ [ ] Test with examples

Time Complexities to Remember:

●​ Hash map operations: O(1) average


●​ List append: O(1), insert: O(n)
●​ Binary search: O(log n)
●​ Sorting: O(n log n)
●​ Tree operations: O(log n) balanced, O(n) worst

Space Complexities:

●​ In-place algorithms: O(1)


●​ Recursive calls: O(depth)
●​ Hash maps: O(n)

🏆 You've Got This!


🐍✨
Remember: Practice consistently, understand the concepts deeply, and don't just memorize
code. Good luck with your interviews!
Javascript

⚡ JavaScript Interview Prep Cheat Sheet


The ultimate guide to ace your JavaScript interviews

📊 Big O Notation - Time & Space Complexity


Notation Name Example Description

O(1) Constant arr[0] Same time regardless of input


size

O(log n) Logarithmic Binary search Reduces problem by half each


step

O(n) Linear for (let i = 0; i < n; Time grows linearly with input
i++)

O(n log n) Linearithmic Merge sort Efficient sorting algorithms

O(n²) Quadratic Nested loops Compare every pair

O(2ⁿ) Exponential Fibonacci (naive) Avoid this!


// O(1) - Constant
function getFirst(arr) {
return arr[0];
}

// O(n) - Linear
function findMax(arr) {
let max = arr[0];
for (let i = 1; i < arr.length; i++) { // visits each element once
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}

// O(n²) - Quadratic
function bubbleSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - 1; j++) { // nested loop = O(n²)
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}

🔢 Data Types & Variables


// Primitive Types
let number = 42;
let string = "Hello World";
let boolean = true;
let undefined_var = undefined;
let null_var = null;
let symbol = Symbol('id');
let bigint = 123n;

// Variable declarations
var oldWay = "function scoped"; // avoid in modern JS
let blockScoped = "block scoped"; // preferred
const constant = "cannot reassign"; // preferred for constants

// Type checking (VERY important for interviews!)


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" (famous JS quirk!)
console.log(Array.isArray([])); // true

// String operations
const str = "JavaScript";
console.log(str[0]); // 'J' - indexing
console.log(str.length); // 10 - length
console.log(str.slice(0, 4)); // 'Java' - slicing
console.log(str.split('')); // ['J','a','v','a','S','c','r','i','p','t']
console.log(str.toLowerCase()); // 'javascript'

🔄 Control Flow
Conditional Statements
// if-else if-else
const score = 85;
let grade;
if (score >= 90) {
grade = 'A';
} else if (score >= 80) {
grade = 'B';
} else {
grade = 'C';
}

// Ternary operator
const result = score >= 60 ? "Pass" : "Fail";

// Switch statement
switch (grade) {
case 'A':
console.log("Excellent!");
break;
case 'B':
console.log("Good job!");
break;
default:
console.log("Keep trying!");
}

// Logical operators
if (score >= 80 && attendance >= 75) {
console.log("Eligible for honors");
}
Loops
// For loops
for (let i = 0; i < 5; i++) { // 0, 1, 2, 3, 4
console.log(i);
}

// For...of (values)
const arr = [1, 2, 3, 4, 5];
for (const value of arr) {
console.log(value); // 1, 2, 3, 4, 5
}

// For...in (keys/indices)
for (const index in arr) {
console.log(index, arr[index]); // 0 1, 1 2, 2 3, 3 4, 4 5
}

// While loops
let count = 0;
while (count < 5) {
console.log(count);
count++;
}

// Loop control
for (let i = 0; i < 10; i++) {
if (i === 3) continue; // skip this iteration
if (i === 7) break; // exit loop
console.log(i);
}

📋 Data Structures
Arrays
// Creation and basic operations - O(1) push, O(n) unshift
const arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4] - O(1) add to end
arr.unshift(0); // [0, 1, 2, 3, 4] - O(n) add to beginning
arr.pop(); // returns 4, arr = [0, 1, 2, 3] - O(1)
arr.shift(); // returns 0, arr = [1, 2, 3] - O(n)
// Important array methods for interviews
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2); // [2, 4, 6, 8, 10]
const evens = numbers.filter(x => x % 2 === 0); // [2, 4]
const sum = numbers.reduce((acc, x) => acc + x, 0); // 15
const found = numbers.find(x => x > 3); // 4
const index = numbers.findIndex(x => x > 3); // 3

// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [3, 4, 5]

Objects (Hash Maps)


// Creation - Average O(1) for get/set
const person = {
name: "Alice",
age: 30,
city: "NYC"
};

// Access properties
console.log(person.name); // "Alice" - dot notation
console.log(person["age"]); // 30 - bracket notation

// Object methods
console.log(Object.keys(person)); // ["name", "age", "city"]
console.log(Object.values(person)); // ["Alice", 30, "NYC"]
console.log(Object.entries(person)); // [["name", "Alice"], ["age", 30], ["city", "NYC"]]

// Object destructuring
const {name, age} = person;
console.log(name); // "Alice"

// Dynamic property names


const key = "occupation";
const updatedPerson = {...person, [key]: "Developer"};

Sets
// Unique elements, O(1) average for add/delete/has
const uniqueNums = new Set([1, 2, 3, 3, 4]); // Set {1, 2, 3, 4}
uniqueNums.add(5);
uniqueNums.delete(1);
console.log(uniqueNums.has(3)); // true
console.log(uniqueNums.size); // 4

// Convert to array
const arr = [...uniqueNums]; // [2, 3, 4, 5]

Maps
// Key-value pairs with any type of key
const map = new Map();
map.set("name", "Alice");
map.set(1, "number key");
map.set(true, "boolean key");

console.log(map.get("name")); // "Alice"
console.log(map.has(1)); // true
console.log(map.size); // 3

// Iterate over map


for (const [key, value] of map) {
console.log(key, value);
}

🔧 Functions
// Function declaration (hoisted)
function greet(name, greeting = "Hello") {
return `${greeting}, ${name}!`;
}

// Function expression (not hoisted)


const greetFunc = function(name) {
return `Hi, ${name}!`;
};

// Arrow functions (lexical this binding)


const greetArrow = (name) => `Hey, ${name}!`;
const square = x => x * x; // single parameter, no parentheses needed

// Rest parameters
function sumAll(...numbers) {
return numbers.reduce((sum, num) => sum + num, 0);
}

// Higher-order functions
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
const evens = numbers.filter(x => x % 2 === 0);
const sum = numbers.reduce((acc, curr) => acc + curr, 0);

// Callback functions
function processArray(arr, callback) {
return arr.map(callback);
}
const squared = processArray([1, 2, 3], x => x * x);

🏗️ Classes & Objects


// ES6 Classes
class Person {
// Constructor
constructor(name, age) {
this.name = name;
this.age = age;
}

// Method
introduce() {
return `Hi, I'm ${this.name} and I'm ${this.age} years old`;
}

// Static method
static species() {
return "Homo sapiens";
}

// Getter
get info() {
return `${this.name} (${this.age})`;
}

// Setter
set age(newAge) {
if (newAge >= 0) {
this._age = newAge;
}
}
}

// Inheritance
class Student extends Person {
constructor(name, age, studentId) {
super(name, age); // Call parent constructor
this.studentId = studentId;
}

study() {
return `${this.name} is studying`;
}
}

// Usage
const alice = new Person("Alice", 25);
const bob = new Student("Bob", 20, "S12345");

// Prototype-based (older style)


function Animal(name) {
this.name = name;
}

Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};

⚠️ Error Handling
// Try-catch-finally
try {
const result = riskyOperation();
console.log(result);
} catch (error) {
console.error("Error occurred:", error.message);
} finally {
console.log("This always runs");
}

// Throwing custom errors


function validateAge(age) {
if (age < 0) {
throw new Error("Age cannot be negative");
}
if (typeof age !== 'number') {
throw new TypeError("Age must be a number");
}
return age;
}

// Custom error class


class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
}
}

🔄 Asynchronous JavaScript
Promises
// Creating a promise
const myPromise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("Operation successful");
} else {
reject(new Error("Operation failed"));
}
});

// Using promises
myPromise
.then(result => console.log(result))
.catch(error => console.error(error))
.finally(() => console.log("Done"));

// Promise.all (wait for all)


Promise.all([promise1, promise2, promise3])
.then(results => console.log(results));

// Promise.race (first to complete)


Promise.race([promise1, promise2])
.then(result => console.log("First:", result));

Async/Await
// Async function
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error("Failed to fetch data:", error);
throw error;
}
}

// Using async function


async function main() {
const data = await fetchData();
console.log(data);
}

// Parallel execution with async/await


async function fetchMultiple() {
const [data1, data2, data3] = await Promise.all([
fetchData1(),
fetchData2(),
fetchData3()
]);
return { data1, data2, data3 };
}

🧮 Essential Algorithms
Searching
// Binary Search - O(log n)
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;

while (left <= right) {


const mid = Math.floor((left + right) / 2);

if (arr[mid] === target) {


return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}

return -1; // not found


}

Sorting
// Quick Sort - O(n log n) average, O(n²) worst
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}

const pivot = arr[Math.floor(arr.length / 2)];


const left = arr.filter(x => x < pivot);
const middle = arr.filter(x => x === pivot);
const right = arr.filter(x => x > pivot);

return [...quickSort(left), ...middle, ...quickSort(right)];


}

// Built-in sorting
const numbers = [3, 1, 4, 1, 5, 9];
numbers.sort((a, b) => a - b); // ascending: [1, 1, 3, 4, 5, 9]
numbers.sort((a, b) => b - a); // descending: [9, 5, 4, 3, 1, 1]

Two Pointers Technique


function twoSumSorted(arr, target) {
let left = 0;
let right = arr.length - 1;

while (left < right) {


const sum = arr[left] + arr[right];

if (sum === target) {


return [left, right];
} else if (sum < target) {
left++;
} else {
right--;
}
}

return [];
}

🎯 Common Interview Patterns


Sliding Window
function maxSumSubarray(arr, k) {
if (arr.length < k) return 0;

// Calculate sum of first window


let windowSum = 0;
for (let i = 0; i < k; i++) {
windowSum += arr[i];
}

let maxSum = windowSum;

// Slide the window


for (let i = k; i < arr.length; i++) {
windowSum = windowSum - arr[i - k] + arr[i];
maxSum = Math.max(maxSum, windowSum);
}

return maxSum;
}
Hash Map for Lookups
function twoSum(nums, target) {
const seen = new Map();

for (let i = 0; i < nums.length; i++) {


const complement = target - nums[i];

if (seen.has(complement)) {
return [seen.get(complement), i];
}

seen.set(nums[i], i);
}

return [];
}

Depth-First Search (DFS)


function dfsRecursive(graph, node, visited = new Set()) {
visited.add(node);
console.log(node);

for (const neighbor of graph[node] || []) {


if (!visited.has(neighbor)) {
dfsRecursive(graph, neighbor, visited);
}
}
}

function dfsIterative(graph, start) {


const visited = new Set();
const stack = [start];

while (stack.length > 0) {


const node = stack.pop();

if (!visited.has(node)) {
visited.add(node);
console.log(node);

// Add neighbors to stack


for (const neighbor of graph[node] || []) {
if (!visited.has(neighbor)) {
stack.push(neighbor);
}
}
}
}
}

🔥 Advanced JavaScript Features


Closures
function createCounter() {
let count = 0;

return function() {
count++;
return count;
};
}

const counter = createCounter();


console.log(counter()); // 1
console.log(counter()); // 2

// Module pattern using closures


const calculator = (function() {
let result = 0;

return {
add: function(x) { result += x; return this; },
multiply: function(x) { result *= x; return this; },
getResult: function() { return result; }
};
})();

calculator.add(5).multiply(2).getResult(); // 10

Prototypes & Inheritance


// Prototype chain
function Animal(name) {
this.name = name;
}

Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};

function Dog(name, breed) {


Animal.call(this, name); // Call parent constructor
this.breed = breed;
}

// Set up inheritance
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
return `${this.name} barks loudly!`;
};

Destructuring & Spread


// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];

// Object destructuring
const {name, age, city = "Unknown"} = person;

// Spread operator
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

const obj1 = {a: 1, b: 2};


const obj2 = {c: 3, d: 4};
const merged = {...obj1, ...obj2}; // {a: 1, b: 2, c: 3, d: 4}

// Function parameters
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}

Template Literals
const name = "Alice";
const age = 30;

// Template literal with interpolation


const greeting = `Hello, my name is ${name} and I am ${age} years old.`;

// Multi-line strings
const multiLine = `
This is a
multi-line
string
`;

// Tagged template literals


function highlight(strings, ...values) {
return strings.reduce((result, string, i) => {
const value = values[i] ? `<mark>${values[i]}</mark>` : '';
return result + string + value;
}, '');
}

const highlighted = highlight`Hello ${name}, you are ${age} years old!`;

⚡ ES6+ Features
Let, Const, and Block Scope
// var vs let vs const
if (true) {
var varVariable = "function scoped";
let letVariable = "block scoped";
const constVariable = "block scoped and immutable";
}

console.log(varVariable); // "function scoped"


// console.log(letVariable); // ReferenceError
// console.log(constVariable); // ReferenceError

Default Parameters
function greet(name = "World", greeting = "Hello") {
return `${greeting}, ${name}!`;
}

console.log(greet()); // "Hello, World!"


console.log(greet("Alice")); // "Hello, Alice!"
console.log(greet("Bob", "Hi")); // "Hi, Bob!"

Modules (Import/Export)
// math.js - Export
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export default function multiply(a, b) {
return a * b;
}

// main.js - Import
import multiply, { PI, add } from './math.js';
import * as Math from './math.js';

console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20
console.log(PI); // 3.14159

💡 Interview Tips & Tricks


String Manipulation
// Common string operations
const str = "Hello World";
console.log(str.toLowerCase()); // "hello world"
console.log(str.toUpperCase()); // "HELLO WORLD"
console.log(str.replace("World", "JS")); // "Hello JS"
console.log(str.split(" ")); // ["Hello", "World"]
console.log(["Hello", "World"].join(" ")); // "Hello World"

// Check if palindrome
function isPalindrome(str) {
const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, '');
return cleaned === cleaned.split('').reverse().join('');
}
// Remove duplicates from array
function removeDuplicates(arr) {
return [...new Set(arr)];
}

// or using filter
function removeDuplicatesFilter(arr) {
return arr.filter((item, index) => arr.indexOf(item) === index);
}

DOM Manipulation (for Frontend roles)


// Selecting elements
const element = document.getElementById('myId');
const elements = document.querySelectorAll('.myClass');
const element2 = document.querySelector('div.container');

// Creating and modifying elements


const newDiv = document.createElement('div');
newDiv.textContent = 'Hello World';
newDiv.classList.add('my-class');
newDiv.setAttribute('data-id', '123');

// Event handling
element.addEventListener('click', function(event) {
event.preventDefault();
console.log('Element clicked!');
});

// Modern event handling with arrow functions


element.addEventListener('click', (e) => {
e.stopPropagation();
console.log('Clicked:', e.target);
});

Performance Tips
// Use const and let instead of var
const config = { apiUrl: 'https://api.example.com' };
let counter = 0;

// Use strict equality


if (value === 42) { /* ... */ } // Good
if (value == 42) { /* ... */ } // Avoid

// Efficient array operations


// Good - use built-in methods
const doubled = numbers.map(x => x * 2);

// Avoid - manual loops when not needed


const doubled2 = [];
for (let i = 0; i < numbers.length; i++) {
doubled2.push(numbers[i] * 2);
}

// Debouncing (common interview question)


function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
}

// Throttling
function throttle(func, delay) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
func.apply(this, args);
}
};
}

🎯 Final Interview Checklist


Before coding:

●​ [ ] Understand the problem completely


●​ [ ] Ask about edge cases and constraints
●​ [ ] Discuss your approach
●​ [ ] Mention time and space complexity
While coding:

●​ [ ] Use meaningful variable names


●​ [ ] Write clean, readable code
●​ [ ] Handle edge cases
●​ [ ] Add comments for complex logic

JavaScript-specific gotchas:

●​ [ ] Remember this binding in arrow functions


●​ [ ] Use === instead of ==
●​ [ ] Handle asynchronous operations properly
●​ [ ] Understand hoisting and scope
●​ [ ] Know prototype chain basics

Common Time Complexities:

●​ Object/Map operations: O(1) average


●​ Array push/pop: O(1), shift/unshift: O(n)
●​ Array sort: O(n log n)
●​ Binary search: O(log n)
●​ Linear search: O(n)

Space Complexities:

●​ In-place algorithms: O(1)


●​ Recursive calls: O(depth)
●​ Hash maps/objects: O(n)
●​ Creating new arrays: O(n)

🏆 You've Got This!


Remember: Practice coding problems daily, understand the concepts deeply, and don't just

⚡✨
memorize syntax. Focus on problem-solving patterns and clean code. Good luck with your
JavaScript interviews!
BIG O NOTATION

**Big O Notation Simply Explained:**

Big O notation is a way to describe how fast an algorithm's runtime or memory usage grows as
the input size increases. It focuses on the **worst-case scenario** and ignores constant factors,
giving you a high-level understanding of efficiency.

### **Key Ideas:**


1. **Measures Scalability** – How does the algorithm perform as the input grows?
2. **Worst-Case Focus** – Describes the upper limit of time/memory needed.
3. **Simplifies Comparison** – Helps choose the most efficient algorithm for large inputs.

### **Common Big O Examples (Fastest to Slowest):**


- **O(1)** – Constant time (e.g., accessing an array index).
- **O(log n)** – Logarithmic time (e.g., binary search).
- **O(n)** – Linear time (e.g., looping through an array).
- **O(n log n)** – Linearithmic time (e.g., efficient sorting like Merge Sort).
- **O(n²)** – Quadratic time (e.g., nested loops, Bubble Sort).
- **O(2ⁿ)** – Exponential time (e.g., naive recursive Fibonacci).
- **O(n!)** – Factorial time (extremely slow, e.g., brute-force traveling salesman).

### **Example:**
- If an algorithm is **O(n)**, doubling the input size roughly doubles the time.
- If it's **O(n²)**, doubling the input could quadruple the time.

### **Why It Matters:**


Big O helps programmers optimize code by identifying bottlenecks and choosing the best
algorithms for large-scale data.

Would you like a real-world analogy or a code example?


### **Big O Notation Explained with Real-World Analogies & Code Examples**

#### **1. Real-World Analogies**


Imagine you’re a chef cooking dishes (processing data). Big O tells you how much longer
cooking takes as orders (input size) increase.

- **O(1) – Instant Serving**


- Example: Putting a pre-made cookie on a plate.
- No matter if you have 1 or 100 customers, time stays the same.

- **O(n) – One by One**


- Example: Making sandwiches to order.
- 10 sandwiches take ~10x longer than 1 sandwich.

- **O(n²) – Nightmare Kitchen**


- Example: Handshaking at a party where everyone greets everyone.
- 5 people = 25 handshakes, 10 people = 100 handshakes!

---

#### **2. Code Examples**


Let’s see how Big O applies to actual code.

##### **O(1) – Constant Time**


```python
def get_first_element(arr):
return arr[0] # Always takes the same time, no matter array size.
```

##### **O(n) – Linear Time**


```python
def find_max(arr):
max_num = arr[0]
for num in arr: # Loops through every element once.
if num > max_num:
max_num = num
return max_num
```

##### **O(n²) – Quadratic Time**


```python
def find_duplicates(arr):
duplicates = []
for i in range(len(arr)): # Outer loop
for j in range(i + 1, len(arr)): # Inner loop
if arr[i] == arr[j]:
duplicates.append(arr[i])
return duplicates
```
*(For 10 elements → ~100 operations, for 100 → ~10,000!)*

##### **O(log n) – Logarithmic Time (Faster!)**


```python
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
```
*(Cutting search space in half each time → super efficient!)*

---

### **Why Should You Care?**


- **O(n) vs O(n²)** could mean seconds vs hours for large data.
- **O(log n)** is way better than **O(n)** for searching (Binary Search vs Linear Search).
- **O(1)** is ideal (hash tables, direct access).

Would you like a comparison of sorting algorithms next? 🚀


REACT

# React Interview Cheat Sheet


*The Ultimate No-BS Guide to Ace Your React Interviews*

---

## 🚀 React Basics
### What is React?
- JavaScript library for building user interfaces (especially SPAs)
- Created by Facebook, focuses on component-based architecture
- Uses Virtual DOM for efficient updates

```javascript
// Simple React Component
function Welcome() {
return <h1>Hello, World!</h1>;
}
```

### JSX (JavaScript XML)


- Syntax extension that looks like HTML but is JavaScript
- Gets compiled to React.createElement() calls
- Must return single parent element (or Fragment)

```javascript
// JSX Example
const element = <h1>Hello {name}!</h1>;

// Compiles to:
const element = React.createElement('h1', null, 'Hello ', name, '!');

// Fragment usage
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);
```
### Components
- Building blocks of React apps
- Two types: Functional (modern) and Class-based (legacy)
- Accept props and return JSX

```javascript
// Functional Component (Preferred)
function Button({ text, onClick, disabled = false }) {
return (
<button onClick={onClick} disabled={disabled}>
{text}
</button>
);
}

// Usage
<Button text="Click me" onClick={() => alert('Clicked!')} />
```

---

## ⚡ Hooks
### useState
- Adds state to functional components
- Returns [currentState, setterFunction]
- State updates are asynchronous

```javascript
function Counter() {
const [count, setCount] = useState(0);

const increment = () => {


setCount(count + 1); // Or setCount(prev => prev + 1)
};

return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
</div>
);
}
```
### useEffect
- Handles side effects (API calls, subscriptions, DOM manipulation)
- Runs after render by default
- Control with dependency array

```javascript
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
// Effect function
setLoading(true);
fetchUser(userId)
.then(userData => {
setUser(userData);
setLoading(false);
});

// Cleanup function (optional)


return () => {
// Cancel requests, clear timers, remove listeners
};
}, [userId]); // Dependency array - effect runs when userId changes

if (loading) return <div>Loading...</div>;


return user ? <div>{user.name}</div> : <div>User not found</div>;
}

// Common useEffect patterns:


useEffect(() => {}, []); // Run once on mount
useEffect(() => {}); // Run on every render
useEffect(() => {}, [dep1, dep2]); // Run when dependencies change
```

### useContext
- Consume context values without prop drilling
- Cleaner alternative to Consumer pattern

```javascript
const ThemeContext = createContext();

function App() {
const [theme, setTheme] = useState('dark');

return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Header />
<Main />
</ThemeContext.Provider>
);
}

function Header() {
const { theme, setTheme } = useContext(ThemeContext);

return (
<header className={theme}>
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
Toggle Theme
</button>
</header>
);
}
```

### Custom Hooks


- Extract and reuse stateful logic
- Must start with "use"
- Can use other hooks inside

```javascript
// Custom hook for counter logic
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);

const increment = useCallback(() => setCount(c => c + 1), []);


const decrement = useCallback(() => setCount(c => c - 1), []);
const reset = useCallback(() => setCount(initialValue), [initialValue]);

return { count, increment, decrement, reset };


}

// Custom hook for API calls


function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(url);
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};

fetchData();
}, [url]);

return { data, loading, error };


}

// Usage
function Counter() {
const { count, increment, decrement, reset } = useCounter(10);

return (
<div>
<span>{count}</span>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}
```

---

## 🗃️ State Management
### Props vs State
- **Props**: Read-only data passed from parent to child
- **State**: Mutable data owned by the component
```javascript
// Props (read-only, passed down)
function Welcome({ name, age }) {
// Cannot modify name or age here
return <h1>Hello {name}, you are {age} years old</h1>;
}

// State (mutable, owned by component)


function Counter() {
const [count, setCount] = useState(0); // This component owns this state
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
}
```

### Lifting State Up


- Move state to closest common ancestor when multiple components need it
- Pass state down as props, pass updaters down as callbacks

```javascript
function App() {
const [temperature, setTemperature] = useState(0);

return (
<div>
<TemperatureInput
temperature={temperature}
onTemperatureChange={setTemperature}
/>
<BoilingVerdict celsius={temperature} />
</div>
);
}

function TemperatureInput({ temperature, onTemperatureChange }) {


return (
<input
value={temperature}
onChange={(e) => onTemperatureChange(Number(e.target.value))}
/>
);
}

function BoilingVerdict({ celsius }) {


return celsius >= 100 ? <p>Water will boil!</p> : <p>Water will not boil.</p>;
}
```

### useReducer
- Alternative to useState for complex state logic
- Similar to Redux pattern
- Good for state with multiple sub-values or complex transitions

```javascript
const initialState = { todos: [], filter: 'all' };

function todoReducer(state, action) {


switch (action.type) {
case 'ADD_TODO':
return {
...state,
todos: [...state.todos, {
id: Date.now(),
text: action.text,
completed: false
}]
};
case 'TOGGLE_TODO':
return {
...state,
todos: state.todos.map(todo =>
todo.id === action.id
? { ...todo, completed: !todo.completed }
: todo
)
};
case 'SET_FILTER':
return { ...state, filter: action.filter };
default:
return state;
}
}

function TodoApp() {
const [state, dispatch] = useReducer(todoReducer, initialState);

const addTodo = (text) => {


dispatch({ type: 'ADD_TODO', text });
};

const toggleTodo = (id) => {


dispatch({ type: 'TOGGLE_TODO', id });
};

return (
<div>
<input onKeyPress={(e) => {
if (e.key === 'Enter') {
addTodo(e.target.value);
e.target.value = '';
}
}} />
{state.todos.map(todo => (
<div key={todo.id} onClick={() => toggleTodo(todo.id)}>
{todo.text} {todo.completed ? '✓' : '○'}
</div>
))}
</div>
);
}
```

---

## ⚡ Performance Optimization
### React.memo
- Higher-order component that memoizes result
- Prevents re-renders if props haven't changed
- Shallow comparison by default

```javascript
// Without memo - re-renders every time parent renders
function ExpensiveComponent({ name, data }) {
console.log('Rendering ExpensiveComponent');
return <div>Hello {name}</div>;
}
// With memo - only re-renders if props change
const OptimizedComponent = React.memo(function ExpensiveComponent({ name, data }) {
console.log('Rendering ExpensiveComponent');
return <div>Hello {name}</div>;
});

// Custom comparison function


const MyComponent = React.memo(function MyComponent({ user }) {
return <div>{user.name}</div>;
}, (prevProps, nextProps) => {
// Return true if props are equal (skip re-render)
return prevProps.user.id === nextProps.user.id;
});
```

### useMemo
- Memoizes expensive calculations
- Only recalculates when dependencies change
- Don't overuse - has its own overhead

```javascript
function ExpensiveList({ items, filter, sortBy }) {
// Expensive calculation memoized
const filteredAndSortedItems = useMemo(() => {
console.log('Filtering and sorting...');
return items
.filter(item => item.name.includes(filter))
.sort((a, b) => a[sortBy] - b[sortBy]);
}, [items, filter, sortBy]); // Only recalculate when these change

return (
<ul>
{filteredAndSortedItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
```

### useCallback
- Memoizes functions to prevent child re-renders
- Useful when passing callbacks to optimized child components
```javascript
function Parent({ items }) {
const [count, setCount] = useState(0);

// Without useCallback - new function on every render


// const handleClick = (id) => { /* handle logic */ };

// With useCallback - same function reference unless dependencies change


const handleClick = useCallback((id) => {
// Handle click logic
console.log('Clicked item:', id);
}, []); // Empty deps because logic doesn't depend on props/state

const handleDelete = useCallback((id) => {


// This depends on items, so include it in deps
const updatedItems = items.filter(item => item.id !== id);
// Update items somehow
}, [items]);

return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
{items.map(item => (
<ExpensiveChild
key={item.id}
item={item}
onClick={handleClick}
onDelete={handleDelete}
/>
))}
</div>
);
}

const ExpensiveChild = React.memo(function ExpensiveChild({ item, onClick, onDelete }) {


console.log('Rendering child for:', item.name);
return (
<div>
<span>{item.name}</span>
<button onClick={() => onClick(item.id)}>Click</button>
<button onClick={() => onDelete(item.id)}>Delete</button>
</div>
);
});
```

---

## 🔄 Lifecycle & Effects


### Effect Dependencies
- Empty array `[]`: Run once on mount
- No array: Run on every render
- With values `[dep1, dep2]`: Run when dependencies change

```javascript
function MyComponent({ userId, theme }) {
// Run once on mount (componentDidMount equivalent)
useEffect(() => {
console.log('Component mounted');
// Good for: initial API calls, event listeners setup
}, []);

// Run on every render (use sparingly!)


useEffect(() => {
console.log('Component rendered');
// Good for: updating document title, etc.
});

// Run when specific values change


useEffect(() => {
fetchUserData(userId);
}, [userId]); // Only run when userId changes

useEffect(() => {
applyTheme(theme);
}, [theme]); // Only run when theme changes

// Multiple dependencies
useEffect(() => {
updateUserTheme(userId, theme);
}, [userId, theme]); // Run when either changes
}
```

### Cleanup Effects


- Prevent memory leaks and unwanted behavior
- Return cleanup function from useEffect
```javascript
function MyComponent() {
useEffect(() => {
// Set up subscription
const subscription = api.subscribe(handleDataUpdate);

// Set up timer
const timer = setInterval(() => {
console.log('Timer tick');
}, 1000);

// Set up event listener


const handleResize = () => setWindowWidth(window.innerWidth);
window.addEventListener('resize', handleResize);

// Cleanup function - runs before next effect or on unmount


return () => {
subscription.unsubscribe();
clearInterval(timer);
window.removeEventListener('resize', handleResize);
};
}, []);

// Cleanup with dependencies


useEffect(() => {
const controller = new AbortController();

fetch(`/api/users/${userId}`, {
signal: controller.signal
}).then(response => {
// Handle response
});

return () => {
controller.abort(); // Cancel request if userId changes
};
}, [userId]);
}
```

---

## 🎨 Common Patterns
### Conditional Rendering
- Show different UI based on conditions
- Multiple techniques available

```javascript
function UserGreeting({ user, isLoading, error }) {
// Early return pattern
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!user) return <div>Please log in</div>;

// Ternary operator (good for simple conditions)


return user.isAdmin ? (
<AdminDashboard user={user} />
):(
<UserDashboard user={user} />
);
}

function App() {
const [user, setUser] = useState(null);
const [showModal, setShowModal] = useState(false);

return (
<div>
{/* Logical AND - show if condition is true */}
{user && <h1>Welcome back, {user.name}!</h1>}
{!user && <LoginButton />}

{/* Conditional with multiple elements */}


{user ? (
<>
<Profile user={user} />
<Settings user={user} />
</>
):(
<GuestWelcome />
)}

{/* Modal pattern */}


{showModal && (
<Modal onClose={() => setShowModal(false)}>
<h2>Modal Content</h2>
</Modal>
)}
</div>
);
}
```

### Lists & Keys


- Render arrays efficiently
- Keys help React identify changes

```javascript
function TodoList({ todos, onToggle, onDelete }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}> {/* Always use unique, stable keys */}
<span
style={{
textDecoration: todo.completed ? 'line-through' : 'none'
}}
onClick={() => onToggle(todo.id)}
>
{todo.text}
</span>
<button onClick={() => onDelete(todo.id)}>Delete</button>
</li>
))}
</ul>
);
}


// Key guidelines:


// Use unique, stable IDs


// Don't use array index if list can change order
// Don't use random values

// Good keys
todos.map(todo => <Todo key={todo.id} todo={todo} />)

// Bad keys (avoid these)


todos.map((todo, index) => <Todo key={index} todo={todo} />) // Index
todos.map(todo => <Todo key={Math.random()} todo={todo} />) // Random
```
### Error Boundaries
- Catch JavaScript errors in component tree
- Must be class components (no hook equivalent)

```javascript
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}

static getDerivedStateFromError(error) {
// Update state to show error UI
return { hasError: true, error };
}

componentDidCatch(error, errorInfo) {
// Log error to reporting service
console.error('Error caught by boundary:', error, errorInfo);
// You can also log to an error reporting service here
}

render() {
if (this.state.hasError) {
// Fallback UI
return (
<div>
<h2>Something went wrong.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
</details>
</div>
);
}

return this.props.children;
}
}

// Usage
function App() {
return (
<ErrorBoundary>
<Header />
<ErrorBoundary> {/* Can nest for granular error handling */}
<MainContent />
</ErrorBoundary>
<Footer />
</ErrorBoundary>
);
}
```

---

## 🚀 Advanced Concepts
### Higher-Order Components (HOC)
- Function that takes a component and returns enhanced component
- Used for cross-cutting concerns (auth, logging, etc.)

```javascript
// HOC for authentication
function withAuth(WrappedComponent) {
return function AuthComponent(props) {
const { user, loading } = useContext(AuthContext);

if (loading) return <div>Loading...</div>;


if (!user) return <LoginForm />;

return <WrappedComponent {...props} user={user} />;


};
}

// HOC for loading states


function withLoading(WrappedComponent) {
return function LoadingComponent({ isLoading, ...props }) {
if (isLoading) return <div>Loading...</div>;
return <WrappedComponent {...props} />;
};
}

// Usage
const ProtectedProfile = withAuth(ProfileComponent);
const ProfileWithLoading = withLoading(withAuth(ProfileComponent));

// Modern alternative: Custom hooks (preferred)


function useAuth() {
const { user, loading } = useContext(AuthContext);
return { user, loading, isAuthenticated: !!user };
}
```

### Render Props


- Share code between components using prop whose value is a function
- Component accepts function as child or prop

```javascript
// Render prop component
function DataFetcher({ url, children }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, [url]);

return children({ data, loading, error });


}

// Usage with render prop


function App() {
return (
<DataFetcher url="/api/users">
{({ data, loading, error }) => {
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <UserList users={data} />;
}}
</DataFetcher>
);
}

// Alternative: Function as children (same concept)


function MouseTracker({ children }) {
const [mouse, setMouse] = useState({ x: 0, y: 0 });

useEffect(() => {
const handleMouseMove = (e) => {
setMouse({ x: e.clientX, y: e.clientY });
};

document.addEventListener('mousemove', handleMouseMove);
return () => document.removeEventListener('mousemove', handleMouseMove);
}, []);

return children(mouse);
}

// Usage
<MouseTracker>
{mouse => (
<div>Mouse position: {mouse.x}, {mouse.y}</div>
)}
</MouseTracker>
```

### Portals
- Render children into DOM node outside parent hierarchy
- Useful for modals, tooltips, dropdowns

```javascript
import { createPortal } from 'react-dom';

function Modal({ children, isOpen, onClose }) {


if (!isOpen) return null;

return createPortal(
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={e => e.stopPropagation()}>
<button className="modal-close" onClick={onClose}>×</button>
{children}
</div>
</div>,
document.getElementById('modal-root') // Must exist in HTML
);
}

function Tooltip({ children, content, isVisible }) {


return (
<>
{children}
{isVisible && createPortal(
<div className="tooltip">{content}</div>,
document.body
)}
</>
);
}

// HTML structure needed:


// <div id="root"></div>
// <div id="modal-root"></div>
```

### Context API (Advanced)


- Avoid prop drilling
- Good for global state (theme, auth, language)

```javascript
// Create context with default value
const AppContext = createContext({
user: null,
theme: 'light',
setUser: () => {},
setTheme: () => {}
});

// Provider component
function AppProvider({ children }) {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState('light');

const value = {
user,
theme,
setUser,
setTheme,
login: async (credentials) => {
const user = await api.login(credentials);
setUser(user);
},
logout: () => {
setUser(null);
api.logout();
}
};

return (
<AppContext.Provider value={value}>
{children}
</AppContext.Provider>
);
}

// Custom hook for consuming context


function useApp() {
const context = useContext(AppContext);
if (!context) {
throw new Error('useApp must be used within AppProvider');
}
return context;
}

// Usage in components
function Header() {
const { user, theme, logout, setTheme } = useApp();

return (
<header className={`header ${theme}`}>
{user ? (
<div>
Welcome, {user.name}
<button onClick={logout}>Logout</button>
</div>
):(
<LoginButton />
)}
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
</header>
);
}
```

---

## 💡 Interview Tips & Common Questions


### Must-Know Concepts
1. **Virtual DOM**: React's reconciliation algorithm
2. **Component Lifecycle**: Mount, update, unmount phases
3. **State vs Props**: Ownership and data flow
4. **Keys in Lists**: Why they matter for performance
5. **Event Handling**: SyntheticEvents and event delegation
6. **Controlled vs Uncontrolled Components**: Form handling approaches

### Common Interview Questions

**Q: What is the Virtual DOM?**


- JavaScript representation of real DOM
- React compares Virtual DOM trees (diffing)
- Only updates changed parts in real DOM (reconciliation)
- Batches updates for better performance

**Q: What are keys and why are they important?**


- Unique identifiers for list items
- Help React identify which items changed/added/removed
- Should be stable and unique (not array index if order can change)
- Improve performance and prevent bugs

**Q: Difference between useState and useReducer?**


- useState: Simple state, single values
- useReducer: Complex state logic, multiple related values
- useReducer: Better for state machines, Redux-like patterns

**Q: When to use useCallback and useMemo?**


- useCallback: Memoize functions (prevent child re-renders)
- useMemo: Memoize expensive calculations
- Don't overuse - measure performance impact

**Q: How to handle forms in React?**


```javascript
// Controlled components (recommended)
function ContactForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
message: ''
});

const handleChange = (e) => {


setFormData({
...formData,
[e.target.name]: e.target.value
});
};

const handleSubmit = (e) => {


e.preventDefault();
// Handle form submission
};

return (
<form onSubmit={handleSubmit}>
<input
name="name"
value={formData.name}
onChange={handleChange}
placeholder="Name"
/>
<input
name="email"
value={formData.email}
onChange={handleChange}
placeholder="Email"
/>
<textarea
name="message"
value={formData.message}
onChange={handleChange}
placeholder="Message"
/>
<button type="submit">Send</button>
</form>
);
}
```

### Performance Best Practices


- Use React DevTools Profiler
- Avoid creating objects/functions in render
- Use React.memo for expensive components
- Implement proper key props for lists
- Code splitting with React.lazy and Suspense
- Avoid unnecessary re-renders

### Testing Knowledge


```javascript
// Component testing with React Testing Library
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test('increments counter when button is clicked', () => {


render(<Counter />);

const button = screen.getByText('+');


const counter = screen.getByText('0');

fireEvent.click(button);

expect(screen.getByText('1')).toBeInTheDocument();
});
```

---

## 🎯 Final Interview Tips


**Before the Interview:**
- Practice coding React components live
- Know your way around Create React App
- Understand modern React (hooks, not classes)
- Review common patterns and best practices

**During the Interview:**


- Think out loud - explain your approach
- Ask clarifying questions about requirements
- Start simple, then add complexity
- Consider edge cases and error handling
- Write clean, readable code with good naming

**Common Coding Challenges:**


- Todo list with CRUD operations
- Fetch and display data from API
- Form with validation
- Counter with increment/decrement
- Search/filter functionality
- Modal or popup component

**Red Flags to Avoid:**


- Using array index as keys in dynamic lists
- Not cleaning up effects (memory leaks)
- Mutating state directly
- Overusing useEffect
- Not handling loading/error states
- Prop drilling instead of context/state management

---

*Remember: React is about thinking in components and data flow. Focus on understanding the
why behind each concept, not just memorizing syntax. Good luck with your interviews!*

You might also like