1. 异步编程的理解和使用
问题代码:
function fetchData(url, callback) {
setTimeout(() => {
// 模拟异步请求
const data = { message: "Hello World" };
callback(data);
}, 1000);
}
fetchData('http://example.com', function(response) {
console.log(response);
// 更多逻辑...
});
解决方案: 使用Promise
或async/await
来简化异步操作。
function fetchData(url) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ message: "Hello World" });
}, 1000);
});
}
// 使用 async/await
async function loadAndProcessData() {
try {
const response = await fetchData('http://example.com');
console.log(response);
// 更多逻辑...
} catch (error) {
console.error("Error fetching data:", error);
}
}
loadAndProcessData();
2. 作用域与闭包
问题代码:
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i); // 打印5次5
}, 1000);
}
解决方案: 使用let
关键字或者立即执行函数表达式(IIFE)创建一个新的作用域。
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i); // 正确打印0到4
}, 1000 * i);
}
3. 事件循环和宏任务/微任务
问题代码:
console.log('Start');
setTimeout(() => console.log('SetTimeout'), 0);
Promise.resolve().then(() => console.log('Promise'));
console.log('End');
解决方案: 理解输出顺序,确保按预期处理宏任务和微任务。
// 输出顺序应该是:
// Start
// End
// Promise
// SetTimeout
4. DOM操作性能
问题代码:
const ul = document.querySelector('ul');
for (let i = 0; i < 1000; i++) {
let li = document.createElement('li');
li.textContent = `Item ${i}`;
ul.appendChild(li);
}
解决方案: 批量更新DOM,例如使用文档片段(DocumentFragment)。
const ul = document.querySelector('ul');
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
let li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
ul.appendChild(fragment);
5. 不必要的全局变量污染
问题代码:
function createGreeting(name) {
greeting = `Hello, ${name}`; // 没有声明greeting变量
}
createGreeting('World');
console.log(greeting); // Hello, World
解决方案: 总是明确地声明变量以避免意外创建全局变量。
function createGreeting(name) {
const greeting = `Hello, ${name}`; // 声明为局部变量
return greeting;
}
console.log(createGreeting('World')); // Hello, World
6. 错误处理不足
问题代码:
function divide(a, b) {
return a / b;
}
console.log(divide(10, 0)); // Infinity
解决方案: 添加适当的错误检查和处理。
function divide(a, b) {
if (b === 0) throw new Error('Division by zero is not allowed.');
return a / b;
}
try {
console.log(divide(10, 0));
} catch (error) {
console.error(error.message);
}
7. 对象和数组的浅拷贝 vs 深拷贝
问题代码:
const obj1 = { name: 'Alice', details: { age: 25 } };
const obj2 = Object.assign({}, obj1);
obj2.details.age = 30;
console.log(obj1.details.age); // 30
解决方案: 使用深拷贝方法如JSON.parse(JSON.stringify())
或库如lodash
。
const obj1 = { name: 'Alice', details: { age: 25 } };
const obj2 = JSON.parse(JSON.stringify(obj1));
obj2.details.age = 30;
console.log(obj1.details.age); // 25
8. 不安全的直接DOM字符串插入
问题代码:
const userName = "<script>alert('XSS');</script>";
document.getElementById('user').innerHTML = `Welcome, ${userName}`;
解决方案: 避免直接插入用户输入,使用文本节点或属性绑定。
const userName = "<script>alert('XSS');</script>";
document.getElementById('user').textContent = `Welcome, ${userName}`;
9. 缺乏模块化设计
问题代码: 所有代码写在一个大文件中,没有分离关注点。
解决方案: 采用模块化设计,比如使用ES6模块。
// math.js
export function add(a, b) {
return a + b;
}
// main.js
import { add } from './math.js';
console.log(add(1, 2));
10. 忽略了浏览器兼容性
问题代码: 使用了特定浏览器特性而忽略了其他浏览器的支持情况。
解决方案: 使用Polyfill或检查环境支持。
if (!String.prototype.startsWith) {
String.prototype.startsWith = function(search, pos) {
return this.substr(!pos || pos >= this.length ? 0 : +pos, search.length) === search;
};
}
1.0 - 完