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 rememberawait
can only be used insideasync
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
, orvar
.
🗂️ 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” andundefined
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 intry/catch
withasync/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 💪