| 1 | Using var in modern code. | Creates hoisting and function-scope confusion. | const name = "John"; |
| 2 | Using == instead of ===. | Can cause unexpected type coercion. | if (age === 18) { allowAccess(); } |
| 3 | Reassigning values unnecessarily. | Makes code harder to reason about. | const total = price + tax; |
| 4 | Using unclear variable names. | Reduces readability and maintainability. | const totalPrice = price + tax; |
| 5 | Creating unnecessary global variables. | Can cause naming conflicts and side effects. | function getTotal() { const total = 100; return total; } |
| 6 | Accessing variables before declaration. | Causes undefined or ReferenceError. | const count = 1; console.log(count); |
| 7 | Expecting let and const to work before declaration. | They are in the temporal dead zone. | let score = 10; |
| 8 | Calling function expressions before assignment. | Function expression is not initialized before execution. | const greet = function() { return "Hi"; }; |
| 9 | Using arrow functions as object methods with this. | Arrow functions do not have their own this. | const user = { name: "John", getName() { return this.name; } }; |
| 10 | Losing this when passing methods as callbacks. | The method context may be lost. | const bound = user.getName.bind(user); |
| 11 | Writing large functions. | Hard to test, debug, and reuse. | function validateEmail(email) { return email.includes("@"); } |
| 12 | Mixing many responsibilities in one function. | Creates tightly coupled code. | function formatPrice(price) { return "$" + price; } |
| 13 | Forgetting to return from map(). | Produces an array of undefined. | const names = users.map(user => user.name); |
| 14 | Using map() for side effects. | map() should transform values. | users.forEach(user => console.log(user.name)); |
| 15 | Using filter() when only one item is needed. | Returns an array instead of one item. | const user = users.find(user => user.id === 1); |
| 16 | Forgetting initial value in reduce(). | Can fail with empty arrays. | const total = prices.reduce((sum, price) => sum + price, 0); |
| 17 | Mutating arrays unexpectedly. | Can cause hidden bugs in state updates. | const updated = [...items, newItem]; |
| 18 | Mutating objects unexpectedly. | Can break predictable state management. | const updatedUser = { ...user, active: true }; |
| 19 | Expecting spread syntax to deep clone objects. | Spread only creates a shallow copy. | const copy = structuredClone(user); |
| 20 | Accessing nested properties without checks. | Can throw errors when data is missing. | const city = user.address?.city; |
| 21 | Using || when 0 is valid. | Falsy values may be replaced incorrectly. | const limit = settings.limit ?? 10; |
| 22 | Comparing objects by reference incorrectly. | Different object references are not equal. | const sameId = userA.id === userB.id; |
| 23 | Using for...in for arrays. | It loops keys, not array values. | for (const item of items) { console.log(item); } |
| 24 | Forgetting array indexes start at 0. | Can access the wrong item. | const firstItem = items[0]; |
| 25 | Sorting numbers without a compare function. | Default sort compares values as strings. | numbers.sort((a, b) => a - b); |
| 26 | Using innerHTML with user input. | Can create security risks. | message.textContent = userInput; |
| 27 | Selecting DOM elements before they exist. | Returns null and causes errors. | document.addEventListener("DOMContentLoaded", init); |
| 28 | Not checking selected elements. | Calling methods on null throws errors. | if (button) { button.addEventListener("click", handleClick); } |
| 29 | Adding duplicate event listeners. | Runs the same logic multiple times. | button.addEventListener("click", handleClick); |
| 30 | Not using event delegation for dynamic lists. | New elements may not have listeners. | list.addEventListener("click", function(event) { console.log(event.target); }); |
| 31 | Forgetting event.preventDefault() on custom form submit. | The page may reload unexpectedly. | form.addEventListener("submit", function(event) { event.preventDefault(); }); |
| 32 | Trusting frontend validation only. | Frontend checks can be bypassed. | // Validate again on the server |
| 33 | Ignoring promise rejections. | Can cause hidden async failures. | fetchUsers().catch(handleError); |
| 34 | Forgetting await. | You may get a Promise instead of actual data. | const users = await fetchUsers(); |
| 35 | Running independent async tasks one by one. | Slower than running in parallel. | const data = await Promise.all([getUsers(), getOrders()]); |
| 36 | Not checking response.ok with Fetch API. | Fetch does not reject for HTTP errors. | if (!response.ok) { throw new Error("Request failed"); } |
| 37 | Forgetting response.json() returns a Promise. | Data may not be available yet. | const data = await response.json(); |
| 38 | Sending objects without JSON.stringify(). | Request body may be incorrect. | body: JSON.stringify(user) |
| 39 | Parsing invalid JSON without handling errors. | Can crash the application. | try { JSON.parse(text); } catch (error) { showError(); } |
| 40 | Using localStorage for sensitive data. | Browser storage can be accessed by scripts. | // Store sensitive data on the server |
| 41 | Forgetting browser storage stores strings only. | Objects become incorrect string values. | localStorage.setItem("user", JSON.stringify(user)); |
| 42 | Leaving intervals running. | Can cause memory leaks and repeated work. | clearInterval(intervalId); |
| 43 | Using setInterval() for slow API polling. | Requests may overlap. | setTimeout(pollAgain, 5000); |
| 44 | Assuming setTimeout(..., 0) runs immediately. | It runs after the current call stack. | setTimeout(callback, 0); |
| 45 | Blocking the UI with heavy synchronous code. | Makes the page freeze. | setTimeout(function() { processChunk(); }, 0); |
| 46 | Using timers for smooth animations. | Animation may be janky. | requestAnimationFrame(animate); |
| 47 | Not debouncing frequent events. | Can cause performance issues. | clearTimeout(timer); timer = setTimeout(search, 300); |
| 48 | Throwing plain strings. | Loses useful error details. | throw new Error("Invalid input"); |
| 49 | Catching errors but doing nothing. | Hides bugs and makes debugging hard. | catch (error) { console.log(error.message); } |
| 50 | Over-engineering simple code. | Makes code harder to maintain. | const total = price + tax; |