├── js ├── debounce.js ├── flatten.js ├── throtthle.js ├── deepClone.md └── closure │ └── closure.md ├── algo ├── BFS.js └── DFS.md ├── CONTRIBUTING.md ├── README.md └── css └── specificity.md /js/debounce.js: -------------------------------------------------------------------------------- 1 | export default function debounce(func, delay) { 2 | let timer; 3 | 4 | return function(...args) { 5 | clearTimeout(timer); 6 | timer = setTimeout(() => { 7 | return func.apply(this, args); 8 | }, delay) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /js/flatten.js: -------------------------------------------------------------------------------- 1 | export default function flatten(value, arr = []) { 2 | if (!value) return; 3 | 4 | for (let i = 0; i < value.length; i++) { 5 | if (Array.isArray(value[i])) { 6 | flatten(value[i], arr); 7 | } else { 8 | arr.push(value[i]); 9 | } 10 | } 11 | 12 | return arr; 13 | } 14 | -------------------------------------------------------------------------------- /js/throtthle.js: -------------------------------------------------------------------------------- 1 | export default function throttle(func, delay) { 2 | let wait = false; 3 | 4 | return function(...args) { 5 | if(wait) { 6 | return; 7 | } 8 | 9 | func.apply(this, args); 10 | wait = true; 11 | setTimeout(() => { 12 | wait = false; 13 | }, delay) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /algo/BFS.js: -------------------------------------------------------------------------------- 1 | //BFS binary tree traversal 2 | 3 | const BFS = (root, arr = []) => { 4 | if(!root) return; 5 | let queue = [root]; 6 | 7 | while(queue.length > 0) { 8 | if(queue[0].left) { 9 | queue.push(queue[0].left); 10 | } 11 | 12 | if(queue[0].right) { 13 | queue.push(queue[0].right); 14 | } 15 | 16 | let removed = queue.shift(); 17 | arr.push(removed); 18 | } 19 | 20 | return arr; 21 | } 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for your interest in contributing! 4 | This repository focuses on **frontend interview fundamentals** — clear, practical, and structured. 5 | 6 | --- 7 | 8 | ## How to contribute 9 | 10 | ### Add new content 11 | - Create a new topic file in the relevant section: 12 | - `html/` 13 | - `css/` 14 | - `js/` 15 | - `react/` 16 | - `algo/` 17 | - Use a clear and descriptive filename (e.g. `css/z-index.md`) 18 | - Focus on interview-relevant concepts 19 | 20 | ### Improve existing content 21 | - Fix typos or unclear explanations 22 | - Add better examples or edge cases 23 | 24 | --- 25 | 26 | ## Topic structure 27 | 28 | Each topic should include: 29 | - Brief explanation 30 | - What interviewers check 31 | - Examples 32 | - Common questions or pitfalls 33 | - References (MDN, specs, trusted sources) 34 | 35 | --- 36 | 37 | ## Contribution steps 38 | 39 | 1. Fork the repository 40 | 2. Commit and push your changes 41 | 3. Open a pull request with a short description 42 | 43 | --- 44 | 45 | ## Guidelines 46 | 47 | - Keep content concise and practical 48 | - Prefer Markdown 49 | - Explain **why**, not just **what** 50 | - Avoid large copy-pasted blocks 51 | 52 | --- 53 | 54 | Thanks for contributing! 55 | -------------------------------------------------------------------------------- /js/deepClone.md: -------------------------------------------------------------------------------- 1 | # Deep clone 2 | 3 | ## JSON-based approach 4 | 5 | ```javascript 6 | // Example input: { role: { user: 'John' } } or { foo: [{ bar: 'baz' }] } 7 | 8 | export default function deepClone(value) { 9 | return JSON.parse(JSON.stringify(value)); 10 | } 11 | ``` 12 | 13 | ## Recursive approach 14 | 15 | ```javascript 16 | //Sometimes, the interviewer can't allow us to use JSON approach so we can try the recursive approach: 17 | 18 | export default function deepClone(value) { 19 | if (typeof value !== 'object' || value === null) { 20 | return value; 21 | } 22 | 23 | if (Array.isArray(value)) { 24 | return value.map((item) => deepClone(item)); 25 | } 26 | 27 | return Object.fromEntries( 28 | Object.entries(value).map(([key, value]) => [key, deepClone(value)]), 29 | ); 30 | } 31 | ``` 32 | 33 | ## Comparison Table 34 | 35 | | Feature | JSON-Based Approach | Recursive Approach | 36 | |--------------------------------|------------------------------------|----------------------------------| 37 | | Handles `undefined` and `Symbol` | ❌ | ✅ | 38 | | Handles `Date` objects | Converts to ISO string | ✅ | 39 | | Circular reference support | ❌ Throws an error | ❌ Throws an error | 40 | | Performance (simple objects) | ✅ Faster | ❌ Slower | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Frontend Interview Prep 2 | 3 | Everything a frontend engineer needs to prepare for interviews. Core web fundamentals, organized in one place. 4 | 5 | ## 📄 HTML 6 | 7 | Core topics that check your understanding of the web platform. 8 | 9 | - [Semantic HTML](html/semantic.md) 10 | - [Forms: validation & submission](html/forms.md) 11 | - [Events & event delegation](html/events.md) 12 | - [Accessibility basics](html/accessibility.md) 13 | 14 | _[View all HTML topics →](html)_ 15 | 16 | ## ✨ CSS 17 | 18 | How browsers resolve styles and layout. 19 | 20 | - [Specificity & cascade](css/specificity.md) 21 | - [Box model](css/box-model.md) 22 | - [Positioning](css/positioning.md) 23 | - [Flexbox vs Grid](css/layout.md) 24 | 25 | _[View all CSS topics →](css)_ 26 | 27 | ## ⚙️ JavaScript 28 | 29 | Language fundamentals frequently tested in interviews. 30 | 31 | - [Closures](js/closure/closure.md) 32 | - [`this`, bind, call, apply](js/this.md) 33 | - [Event loop](js/event-loop.md) 34 | - [Async JavaScript](js/async.md) 35 | 36 | _[View all JavaScript topics →](js)_ 37 | 38 | ## ⚛️ React 39 | 40 | Modern frontend architecture and patterns. 41 | 42 | - [Hooks](react/hooks.md) 43 | - [Controlled vs uncontrolled components](react/forms.md) 44 | - [Performance optimization](react/performance.md) 45 | - [State management](react/state.md) 46 | 47 | _[View all React topics →](react)_ 48 | 49 | ## 🧩 Algorithms 50 | 51 | JavaScript algorithms and problem solving. 52 | 53 | *Coming soon - building out common interview patterns* 54 | 55 | _[View all algorithms →](algo)_ 56 | 57 | --- 58 | 59 | ## Contributing 60 | 61 | Want to contribute? Please read [CONTRIBUTING.md](CONTRIBUTING.md). 62 | 63 | --- 64 | 65 | *You shall pass* 🧙♂️ 66 | -------------------------------------------------------------------------------- /algo/DFS.md: -------------------------------------------------------------------------------- 1 | 2 | # Depth-First Search (DFS) 3 | 4 | ## What is DFS? 5 | DFS is a graph/tree traversal algorithm that explores as deep as possible before backtracking. It is useful for solving problems that require exhaustive search, pathfinding, or backtracking. 6 | 7 | ## When to Use DFS? 8 | 9 | - **Exhaust All Possibilities** → When checking all potential solutions before deciding the best one (e.g., solving a maze). 10 | - **Count All Possible Paths** → When finding every way from source to destination (e.g., counting ways to reach a target). 11 | - **Backtracking Problems** → When solving problems that involve undoing decisions (e.g., Sudoku, N-Queens). 12 | - **Detecting Cycles in a Graph** → When checking if a directed or undirected graph has cycles. 13 | - **Navigating File System Structures** → When recursively searching directories (e.g., searching for a file). 14 | 15 | ```javascript 16 | //DFS binary tree traversal stack (pre-order) 17 | function dfs(node) { 18 | if (!node) return; 19 | 20 | const stack = [node]; 21 | const result = []; 22 | 23 | while (stack.length > 0) { 24 | const current = stack.pop(); 25 | result.push(current.val); 26 | 27 | if (current.right) { 28 | stack.push(current.right); 29 | } 30 | 31 | if (current.left) { 32 | stack.push(current.left); 33 | } 34 | } 35 | 36 | return result; 37 | } 38 | ``` 39 | 40 | ```javascript 41 | //DFS binary tree traversal recursion (pre-order) 42 | 43 | function dfs(node, arr = []) { 44 | if (!node) return; 45 | 46 | arr.push(node.val); 47 | if(node.left) dfs(node.left, arr); 48 | if(node.right) dfs(node.right, arr); 49 | 50 | return arr; 51 | } 52 | ``` 53 | 54 | ## Comparison Table 55 | 56 | | Feature | Recursive Approach | Stack-Based Approach | 57 | |----------------------------------|--------------------------------|--------------------------------| 58 | | Memory Usage | Higher (due to call stack) | Lower (explicit stack) | 59 | | Handles Deep Trees | ❌ Risk of stack overflow | ✅ Avoids call stack limits | 60 | | Performance (shallow trees) | ✅ Generally faster | ❌ Slightly slower | 61 | | Code Readability | ✅ More concise, easier to read| ❌ More complex | 62 | 63 | 64 | ## Complexity Analysis 65 | 66 | - **V**: Number of nodes (vertices) in a graph. 67 | - **E**: Number of edges (connections) between nodes. 68 | - **H**: Means the height of the tree 69 | --- 70 | - **Graph (Adjacency List):** **O(V + E)** (visits each node and edge once). 71 | - **Tree (Binary Tree):** **O(N)** (visits each node once). 72 | --- 73 | - **Recursive DFS:** **O(V)** (due to call stack depth). 74 | - **Stack-Based DFS:** **O(V)** (explicit stack). 75 | 76 | ### Complexity Table 77 | 78 | | Case | Time Complexity | Space Complexity | 79 | |-----------------------------|-----------------|------------------| 80 | | **Graph (Adjacency List)** | O(V + E) | O(V) | 81 | | **Tree (Binary Tree)** | O(N) | O(H) | 82 | | **Worst Case (Deep Recursion)** | O(V + E) | O(V) | 83 | -------------------------------------------------------------------------------- /css/specificity.md: -------------------------------------------------------------------------------- 1 | # CSS Specificity 2 | 3 | ## How specificity works 4 | 5 | CSS specificity is calculated using a four-part system: `(0,0,0,0)`. Higher values on the left have higher priority. 6 | 7 | | Selector type | Example | Specificity | 8 | |:--------------|:--------|:-----------:| 9 | | Universal / Combinators | `*`, `+`, `>`, `~` | `(0,0,0,0)` | 10 | | Elements & Pseudo-elements | `div`, `::before` | `(0,0,0,1)` | 11 | | Classes, Attributes, Pseudo-classes | `.menu`, `[href]`, `:hover` | `(0,0,1,0)` | 12 | | ID selectors | `#header` | `(0,1,0,0)` | 13 | | Inline styles | `style="..."` | `(1,0,0,0)` | 14 | 15 | ### Key rules 16 | 17 | 1. **Left-to-right comparison** - CSS compares each position from left to right and stops at the first difference. One ID `(0,1,0,0)` beats a million classes `(0,0,1000000,0)` because the ID position is checked first. 18 | 2. **Source order matters** - If specificity is equal, the last rule wins 19 | 3. **Inheritance has no specificity** - Inherited styles are always overridden by direct rules 20 | 21 | > 💡 **Fun fact:** In ancient browsers like IE6, you could override an ID with 256+ classes due to how specificity was stored as an 8-bit number. Modern browsers fixed this bug. 22 | 23 | ### Examples 24 | ```css 25 | #header .menu li a { } /* (0,1,1,3) — 1 ID + 1 class + 3 elements */ 26 | .menu li a { } /* (0,0,1,2) — 1 class + 2 elements */ 27 | a { } /* (0,0,0,1) — 1 element */ 28 | ``` 29 | 30 | ## Modern pseudo-classes: `:is()` vs `:where()` 31 | 32 | Both group selectors but affect specificity differently. 33 | 34 | **`:is()` takes the highest specificity from its arguments:** 35 | ```css 36 | :is(.list, #special) { } /* (0,1,0,0) from #special */ 37 | ``` 38 | 39 | **`:where()` always has zero specificity:** 40 | ```css 41 | :where(.list, #special) { } /* (0,0,0,0) */ 42 | ``` 43 | 44 | This makes `:where()` useful for creating easily-overridable default styles. 45 | 46 | ## The `!important` exception 47 | 48 | `!important` bypasses normal specificity rules entirely. To override an `!important` rule, you need another `!important` with higher specificity or one that appears later in the code. 49 | 50 | > ⚠️ **Avoid unless absolutely necessary** - prefer solving specificity issues with better selector design. 51 | 52 | ## Best practices 53 | 54 | - ✅ **Prefer classes over IDs** - IDs have very high specificity, making them hard to override 55 | - ✅ **Keep specificity flat** - Avoid deep nesting. Aim for 2-3 levels max 56 | - ✅ **Avoid long selector chains** - Each additional selector increases coupling 57 | - ⚠️ **Avoid `!important`** - It creates escalation wars and maintenance problems 58 | - 💡 **Use `:where()` for resets** - Zero specificity makes base styles easy to override 59 | 60 | ## Practice question 61 | 62 | Which color will be applied? 63 | ```css 64 | #milan { color: red; } 65 | .container .paris { color: blue; } 66 | div.paris { color: green; } 67 | ``` 68 | ```html 69 |