JavaScript is an incredibly powerful and flexible language — but that flexibility comes with a price: subtle quirks and gotchas that even seasoned developers stumble into.

Whether you're building enterprise applications or working on your next side project, these are the 10 most common JavaScript pitfalls that can cause unexpected behavior, bugs, or even security vulnerabilities.

📌 This post will help you identify, understand, and avoid these common traps, and write cleaner, safer, and more predictable code.


🚫 1. Confusing == vs ===

The == operator performs type coercion, while === checks for strict equality.

0 == false   // true 😱
0 === false  // false ✅

✅ Always use === unless you really understand coercion rules.


🧠 2. Using var Instead of let or const

var is function-scoped and hoisted, which can lead to unpredictable behavior.

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000); // 3, 3, 3
}

Use let or const to get block-scoped, predictable results.


🌀 3. Misunderstanding Asynchronous Behavior

JavaScript’s async nature can be tricky:

const result = fetchData(); // ❌ Doesn't wait!
console.log(result);

✅ Always await async functions, and remember await can only be used inside async functions.


🧨 4. Modifying Objects/Arrays by Reference

Objects and arrays are reference types:

const a = { count: 1 };
const b = a;
b.count = 2;
console.log(a.count); // 2 ❗

🛡 Use structuredClone, spread ({ ...a }), or libraries like Lodash for immutability.


🔁 5. Incorrect for...in vs for...of Usage

  • for...in is for object keys
  • for...of is for iterables like arrays
const arr = ['a', 'b', 'c'];
for (let i in arr) console.log(i); // "0", "1", "2"
for (let i of arr) console.log(i); // "a", "b", "c"

🧮 6. Floating Point Math Woes

0.1 + 0.2 === 0.3 // false 😤

✅ Use libraries like decimal.js or work with integers when precision matters (e.g. cents instead of dollars).


📦 7. Leaking Variables to Global Scope

In browsers:

function test() {
  leakedVar = "oops"; // 👻 becomes global
}

✅ Always declare variables with let, const, or var.


🗂️ 8. Overusing null and undefined Interchangeably

typeof null        // "object" 😬
typeof undefined   // "undefined"

💡 Use one consistently in your app. Many devs use null for “intentional empty” and undefined for “not set”.


🧪 9. Not Handling Errors in Async Code

Uncaught promise errors can crash your app:

fetch('/data')
  .then(res => res.json())
  .then(data => doSomething(data));
// No `.catch()` 😵

✅ Always add .catch() or wrap in try/catch with async/await.


🧵 10. Assuming JavaScript is Single-threaded (Hint: It's not entirely)

JS has one main thread, but async tasks like fetch, setTimeout, and event listeners use the event loop.

🤯 Misunderstanding this can lead to race conditions or unhandled state updates in frameworks like React or Vue.


✅ Final Thoughts

JavaScript is powerful — but with great power comes great... undefined. 🕸️

Avoiding these common pitfalls will make your code more maintainable, more secure, and way easier for others (and your future self) to read.


💬 Have you encountered any of these? Got your own JavaScript “gotchas” to share?

Drop them in the comments below 👇

Let’s help each other write better JS 💪