JavaScript Common Mistakes

***

Avoid common JavaScript mistakes with our comprehensive cheat sheet. Perfect for developers seeking to improve their code quality ๐Ÿ› ๏ธ.

JavaScript is a flexible and powerful language, but it can be easy to make mistakes, especially for beginners. Here is a list of common mistakes and how to avoid them.

1. Incorrect Use of == and ===

Problem: Using == (loose equality) instead of === (strict equality) can lead to unexpected type coercions.

console.log(0 == "0"); // true
console.log(0 === "0"); // false

Solution: Always use === unless you have a specific reason to use ==.

console.log(0 === "0"); // false

2. Misunderstanding this

Problem: The value of this changes depending on how a function is called.

const obj = {
  value: 42,
  method: function() {
    console.log(this.value);
  }
};
const method = obj.method;
method(); // undefined

Solution: Use arrow functions or bind this correctly.

const obj = {
  value: 42,
  method: function() {
    console.log(this.value);
  }
};
const method = obj.method.bind(obj);
method(); // 42
 
// Or use an arrow function
const obj = {
  value: 42,
  method: () => {
    console.log(obj.value);
  }
};
obj.method(); // 42

3. Using var Instead of let or const

Problem: var is function-scoped and can lead to unexpected behavior.

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

Solution: Use let or const which are block-scoped.

for (let i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 1000);
}
// Outputs: 0, 1, 2, 3, 4

4. Not Using const for Constants

Problem: Accidentally reassigning variables that should not change.

const a = 1;
a = 2; // TypeError: Assignment to constant variable.

Solution: Use const for variables that should not be reassigned.

const a = 1;
// a = 2; // This will throw an error

5. Forgetting to Declare Variables

Problem: Implicit global variables can lead to bugs.

function foo() {
  bar = 42; // Implicit global variable
}
foo();
console.log(bar); // 42

Solution: Always declare variables using let, const, or var.

function foo() {
  let bar = 42;
}
foo();
console.log(bar); // ReferenceError: bar is not defined

6. Not Handling Asynchronous Code Properly

Problem: Callback hell or not using Promises/async-await correctly.

setTimeout(() => {
  console.log("First");
  setTimeout(() => {
    console.log("Second");
    setTimeout(() => {
      console.log("Third");
    }, 1000);
  }, 1000);
}, 1000);

Solution: Use Promises or async/await for better readability.

// Using Promises
new Promise(resolve => {
  setTimeout(() => {
    console.log("First");
    resolve();
  }, 1000);
})
.then(() => new Promise(resolve => {
  setTimeout(() => {
    console.log("Second");
    resolve();
  }, 1000);
}))
.then(() => {
  setTimeout(() => {
    console.log("Third");
  }, 1000);
});
 
// Using async/await
async function sequentialLog() {
  await new Promise(resolve => setTimeout(() => {
    console.log("First");
    resolve();
  }, 1000));
  
  await new Promise(resolve => setTimeout(() => {
    console.log("Second");
    resolve();
  }, 1000));
  
  await new Promise(resolve => setTimeout(() => {
    console.log("Third");
  }, 1000));
}
sequentialLog();

7. Misusing Arrow Functions

Problem: Arrow functions do not have their own this or arguments.

const obj = {
  value: 42,
  method: () => {
    console.log(this.value);
  }
};
obj.method(); // undefined

Solution: Use regular functions when this context is required.

const obj = {
  value: 42,
  method: function() {
    console.log(this.value);
  }
};
obj.method(); // 42

8. Not Using break in switch Statements

Problem: Falling through to the next case unintentionally.

let x = 1;
switch (x) {
  case 1:
    console.log("One");
  case 2:
    console.log("Two");
}
// Outputs: "One", "Two"

Solution: Use break to prevent fall-through.

let x = 1;
switch (x) {
  case 1:
    console.log("One");
    break;
  case 2:
    console.log("Two");
}

9. Incorrectly Using for...in to Iterate Over Arrays

Problem: for...in iterates over enumerable properties, not just array elements.

let arr = [1, 2, 3];
for (let i in arr) {
  console.log(i); // "0", "1", "2"
}

Solution: Use for...of to iterate over array elements.

for (let value of arr) {
  console.log(value); // 1, 2, 3
}

10. Modifying Objects in Place

Problem: Unintentionally mutating objects can lead to bugs, especially in functional programming or React.

let obj = { a: 1 };
let newObj = obj;
newObj.a = 2;
console.log(obj.a); // 2

Solution: Create new objects instead of mutating existing ones.

let obj = { a: 1 };
let newObj = { ...obj, a: 2 };
console.log(obj.a); // 1
console.log(newObj.a); // 2

11. Misunderstanding NaN

Problem: NaN is not equal to itself.

console.log(NaN === NaN); // false

Solution: Use isNaN() or Number.isNaN() to check for NaN.

console.log(Number.isNaN(NaN)); // true

12. Using parseInt Incorrectly

Problem: parseInt can produce unexpected results if the string starts with a non-digit.

console.log(parseInt("08")); // 8
console.log(parseInt("09")); // 9
console.log(parseInt("0x10")); // 16 (hexadecimal)

Solution: Always provide a radix to parseInt.

console.log(parseInt("08", 10)); // 8
console.log(parseInt("09", 10)); // 9

13. Forgetting default in switch Statements

Problem: Not handling unexpected cases.

let fruit = "banana";
switch (fruit) {
  case "apple":
    console.log("Apple");
    break;
  case "orange":
    console.log("Orange");
    break;
  // No default case
}

Solution: Always include a default case.

switch (fruit) {
  case "apple":
    console.log("Apple");
    break;
  case "orange":
    console.log("Orange");
    break;
  default:
    console.log("Unknown fruit");
}

14. Incorrectly Using Math.random()

Problem: Not getting the desired range of random numbers.

let randomNum = Math.random() * 10; // Between 0 and 10

Solution: Use proper scaling and rounding.

let randomNum = Math.floor(Math.random() * 10); // Integer between 0 and 9
let randomNumInRange = Math.floor(Math.random() * (max - min + 1)) + min; // Integer between min and max

15. Not Using event.preventDefault() and event.stopPropagation()

Problem: Default actions and event bubbling can cause issues.

document.querySelector("a").addEventListener("click", function(event) {
  // Default action (navigation) occurs
});

Solution: Use preventDefault and stopPropagation to control event behavior.

document.querySelector("a").addEventListener("click", function(event) {
  event.preventDefault(); // Prevent navigation
  event.stopPropagation(); // Stop event from bubbling up
});

This cheat sheet highlights common JavaScript mistakes and their solutions, helping you

write more robust and error-free code.