-
Global Variables:
-
Problem: Forgetting to use
var
,let
, orconst
can create global variables unintentionally. -
Solution: Always declare variables with
let
orconst
.
-
Problem: Forgetting to use
// Bad
x = 10;
// Good
let x = 10;
-
Variable Hoisting:
-
Problem: Variables declared with
var
are hoisted to the top of their scope, which can lead to unexpected behavior. -
Solution: Use
let
andconst
to avoid hoisting issues.
-
Problem: Variables declared with
console.log(x); // undefined
var x = 5;
// Use let or const
console.log(y); // ReferenceError: y is not defined
let y = 5;
-
Function Hoisting:
- Problem: Function declarations are hoisted, but function expressions are not.
// This works
greet();
function greet() {
console.log('Hello');
}
// This does not work
sayHi(); // TypeError: sayHi is not a function
var sayHi = function() {
console.log('Hi');
};
-
this
Keyword:-
Problem: The value of
this
can change depending on the context in which a function is called. -
Solution: Use arrow functions or
.bind()
to maintain the correctthis
context.
-
Problem: The value of
function Person(name) {
this.name = name;
setTimeout(function() {
console.log(this.name); // undefined
}, 1000);
}
// Using arrow function
function Person(name) {
this.name = name;
setTimeout(() => {
console.log(this.name); // Correctly logs the name
}, 1000);
}
-
Equality Operators:
-
Problem: The
==
operator performs type coercion, which can lead to unexpected results. -
Solution: Use the
===
operator for strict equality checks.
-
Problem: The
console.log(0 == '0'); // true
console.log(0 === '0'); // false
-
Falsy Values:
-
Problem: Understanding what values are considered falsy (
false
,0
,''
,null
,undefined
,NaN
). - Solution: Be mindful when checking for truthy or falsy values.
-
Problem: Understanding what values are considered falsy (
if (0) {
console.log('This will not run');
}
-
Closure Scope:
- Problem: Loop variables in closures can lead to unexpected behavior.
-
Solution: Use
let
in loops to ensure block scope.
for (var i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i); // Logs 4, 4, 4
}, i * 1000);
}
// Using let
for (let i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i); // Logs 1, 2, 3
}, i * 1000);
}
-
Default Parameters:
- Problem: Older JavaScript versions don't support default parameters.
- Solution: Use ES6 default parameters or logical operators.
function greet(name) {
name = name || 'Guest';
console.log('Hello ' + name);
}
// ES6 Default parameters
function greet(name = 'Guest') {
console.log(`Hello ${name}`);
}
-
Array Methods:
-
Problem: Confusing
map
,forEach
,filter
,reduce
. - Solution: Understand the purpose and return values of each method.
-
Problem: Confusing
const numbers = [1, 2, 3, 4];
numbers.forEach(n => console.log(n)); // Logs each number
const doubled = numbers.map(n => n * 2); // Returns [2, 4, 6, 8]
const evens = numbers.filter(n => n % 2 === 0); // Returns [2, 4]
const sum = numbers.reduce((total, n) => total + n, 0); // Returns 10
-
Async/Await:
- Problem: Misunderstanding how to handle asynchronous code.
-
Solution: Use
async
andawait
for cleaner asynchronous code.
async function fetchData() { try { const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); } catch (error) { console.error('Error fetching data', error); } }
Understanding these common pitfalls can help you write more robust and maintainable JavaScript code. If you have any specific scenarios or examples you'd like to delve into, feel free to ask!