In this comprehensive guide, we will explore 10 common JavaScript mistakes, explain why they happen, and show you how to fix them with real-world examples.
Let's dive in! 🎯
1️⃣ Using var
Instead of let
and const
Problem: The var
keyword has function-scoped behavior that can cause unexpected issues due to hoisting.
❌ Bad Code (Using var
)
function example() {
if (true) {
var name = "John";
}
console.log(name); // No error, but this can be dangerous
}
🔴 Issue: var
does not have block scope, meaning name
is accessible outside the if
block.
✅ Good Code (Using let
and const
)
function example() {
if (true) {
let name = "John";
console.log(name); // ✅ Works fine
}
console.log(name); // ❌ ReferenceError: name is not defined
}
✅ Why is this better?
✔ let
and const
have block scope, preventing accidental overwrites.
✔ const
should be used for values that never change.
2️⃣ Forgetting ===
Instead of ==
Problem: JavaScript allows loose comparison (==
), which can lead to unexpected type coercion.
❌ Bad Code (Using ==
)
console.log(0 == "0"); // true 😱
console.log(false == ""); // true 🤯
🔴 Issue: JavaScript automatically converts types, leading to unpredictable results.
✅ Good Code (Using ===
)
console.log(0 === "0"); // false ✅
console.log(false === ""); // false ✅
✅ Why is this better?
✔ ===
ensures both type and value match.
✔ Avoids unexpected type conversions.
3️⃣ Not Handling Asynchronous Code Properly
Problem: Using synchronous code where asynchronous handling is required can cause issues.
❌ Bad Code (Forgetting await
)
async function fetchData() {
let data = fetch("https://api.example.com/data");
console.log(data); // ❌ Returns a Promise, not data
}
🔴 Issue: fetch()
is asynchronous, so it returns a Promise, not the actual data.
✅ Good Code (Using await
)
async function fetchData() {
let response = await fetch("https://api.example.com/data");
let data = await response.json();
console.log(data); // ✅ Now we get actual data
}
✅ Why is this better?
✔ Ensures data is properly fetched before proceeding.
✔ Prevents Promise-related bugs.
4️⃣ Modifying an Object While Iterating Over It
Problem: Modifying an object or array during iteration leads to unexpected behavior.
❌ Bad Code (Modifying While Iterating)
let users = [{ id: 1 }, { id: 2 }, { id: 3 }];
users.forEach((user, index) => {
if (user.id === 2) {
users.splice(index, 1); // ❌ Dangerous operation
}
});
console.log(users); // Unpredictable results
🔴 Issue: The loop is still running while modifying the array, leading to skipped elements.
✅ Good Code (Filtering Instead)
users = users.filter(user => user.id !== 2);
console.log(users); // ✅ Correctly removes item without issues
✅ Why is this better?
✔ Prevents looping issues.
✔ Makes the code easier to read and maintain.
5️⃣ Using parseInt()
Without a Radix
Problem: parseInt()
can interpret numbers in unexpected bases if no radix is provided.
❌ Bad Code (No Radix)
console.log(parseInt("08")); // ❌ Returns 0 in some browsers
🔴 Issue: Some versions of JavaScript assume octal (base 8) for numbers starting with 0.
✅ Good Code (Always Specify a Radix)
console.log(parseInt("08", 10)); // ✅ Correct output: 8
✅ Why is this better?
✔ Ensures correct number interpretation.
✔ Works across all browsers consistently.
6️⃣ Ignoring Function Scope When Using this
Problem: JavaScript’s this
behaves differently in arrow functions and regular functions.
❌ Bad Code (this
Losing Context)
class User {
constructor(name) {
this.name = name;
}
printName() {
setTimeout(function () {
console.log(this.name); // ❌ Undefined
}, 1000);
}
}
new User("John").printName();
🔴 Issue: this
inside setTimeout
refers to the global object, not User
.
✅ Good Code (Using Arrow Functions)
class User {
constructor(name) {
this.name = name;
}
printName() {
setTimeout(() => {
console.log(this.name); // ✅ Correctly prints "John"
}, 1000);
}
}
✅ Why is this better?
✔ Arrow functions inherit this
from their surrounding scope.
7️⃣ Overwriting Built-in Prototypes
Problem: Modifying built-in prototypes (Array
, Object
, etc.) can break third-party libraries.
❌ Bad Code (Modifying Array
Prototype)
Array.prototype.removeFirst = function () {
this.shift();
};
🔴 Issue: Extending built-in prototypes can cause unexpected side effects.
✅ Good Code (Using Utility Functions)
function removeFirst(arr) {
return arr.slice(1);
}
✅ Why is this better?
✔ Keeps built-in objects intact.
✔ Safer for third-party libraries.
8️⃣ Ignoring Floating Point Precision Issues
Problem: JavaScript cannot precisely represent some decimal numbers.
❌ Bad Code (Relying on Floating-Point Precision)
console.log(0.1 + 0.2 === 0.3); // ❌ false
🔴 Issue: Due to floating-point math, 0.1 + 0.2 !== 0.3 exactly.
✅ Good Code (Using .toFixed()
or Math Libraries)
console.log((0.1 + 0.2).toFixed(2) === "0.30"); // ✅ true
✅ Why is this better?
✔ Ensures consistent rounding.
✔ Avoids unexpected calculations.
9️⃣ Not Handling Errors in Promises
Problem: Unhandled errors in asynchronous code can crash applications.
❌ Bad Code (No .catch()
)
fetch("https://api.example.com/data")
.then(response => response.json());
🔴 Issue: If the request fails, there’s no error handling.
✅ Good Code (Adding .catch()
)
fetch("https://api.example.com/data")
.then(response => response.json())
.catch(error => console.error("Error fetching data:", error));
✅ Why is this better?
✔ Prevents unhandled rejections.
🔟 Blocking the Event Loop with Heavy Computation
Problem: JavaScript runs on a single thread, meaning heavy operations freeze the UI.
❌ Bad Code (Blocking the Event Loop)
for (let i = 0; i < 1e9; i++) { } // ❌ Freezes the browser
✅ Good Code (Using setTimeout()
)
function processLargeTask() {
setTimeout(() => {
for (let i = 0; i < 1e6; i++) { } // ✅ Runs without freezing
}, 0);
}
✅ Why is this better?
✔ Prevents UI from becoming unresponsive.
📌 Conclusion
By avoiding these 10 JavaScript mistakes, you can write cleaner, faster, and more reliable code. 🚀
Comments
Post a Comment
Leave Comment