优秀的编程知识分享平台

网站首页 > 技术文章 正文

焦虑!代码漏洞频出?7 个 JavaScript 技巧助你力挽狂澜

nanyue 2025-05-16 15:16:11 技术文章 2 ℃


前端开发的日常,不是在填坑,就是在填坑的路上!JavaScript 代码跑起来 bug 频出,页面卡顿到崩溃,好不容易写好的功能,上线就 “翻车”,简直让人头秃!别慌!今天带来 7 个超实用的 JavaScript 实战技巧,从数据处理到性能优化,无论是 React、Vue 项目,还是原生开发,都能帮你轻松化解难题,力挽狂澜!

一、数组排序的「隐藏玄机」:sort方法的正确打开方式

在处理数据列表时,给数组排序是再常见不过的操作。但直接使用sort方法,往往会得到意想不到的结果,这是很多开发者容易踩的坑!

// 定义一个包含数字的数组
const numbers = [30, 15, 8, 1];
// 使用sort方法对数组进行排序(这里错误地未传入比较函数)
const sortedNumbers = numbers.sort();
// 输出排序后的数组(结果不符合预期)
console.log(sortedNumbers);
// 预期输出 [1, 8, 15, 30],实际输出 [1, 15, 30, 8]

sort方法默认会将元素转换为字符串,并按照 Unicode 码位进行排序。所以,当我们对数字数组排序时,必须传入一个比较函数。

// 定义一个包含数字的数组
const numbers = [30, 15, 8, 1];
// 使用sort方法并传入比较函数,对数组进行正确排序
const sortedNumbers = numbers.sort((a, b) => a - b);
// 输出排序后的数组
console.log(sortedNumbers);
// 输出 [1, 8, 15, 30]

二、async/await:异步操作的「终极形态」,却暗藏「危机」

用Promise处理异步请求时,代码层层嵌套,宛如 “迷宫”,不仅难写还难读。async/await的出现,让异步代码变得简洁直观,就像同步代码一样。但如果使用不当,也会埋下 “定时炸弹”!

// 模拟一个异步函数,返回Promise对象
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ message: '数据获取成功' });
}, 1000);
});
}
// 定义一个async函数(这里错误地未处理错误情况)
async function getData() {
const data = await fetchData();
console.log(data);
}
// 调用async函数
getData();

上述代码中,如果fetchData函数执行失败,程序就会直接报错终止。为了让代码更加健壮,我们需要添加错误处理机制。

// 模拟一个异步函数,返回Promise对象
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ message: '数据获取成功' });
}, 1000);
});
}
// 定义一个async函数,并添加错误处理
async function getData() {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error('数据获取失败:', error);
}
}
// 调用async函数
getData();

三、localStorage使用误区:数据存储的「正确姿势」

想要在浏览器中存储用户信息、配置数据等,localStorage是一个不错的选择。但如果使用不当,可能会导致数据丢失或读取异常。

// 定义要存储的用户数据
const user = { name: 'Bob', age: 30 };
// 直接将对象存储到localStorage(这是错误的做法)
localStorage.setItem('user', user);
// 从localStorage中获取数据
const retrievedUser = localStorage.getItem('user');
// 输出获取到的数据(会发现是[object Object])
console.log(retrievedUser);

localStorage只能存储字符串类型的数据,所以在存储对象时,我们需要先将其转换为 JSON 字符串。

// 定义要存储的用户数据
const user = { name: 'Bob', age: 30 };
// 将对象转换为JSON字符串后存储到localStorage
localStorage.setItem('user', JSON.stringify(user));
// 从localStorage中获取数据,并转换回对象
const retrievedUser = JSON.parse(localStorage.getItem('user'));
// 输出获取到的数据
console.log(retrievedUser);
// 输出 { name: 'Bob', age: 30 }

四、事件委托:高效处理事件的「秘密武器」

当页面中有大量元素需要添加事件监听时,直接为每个元素绑定事件,不仅代码冗余,还会影响性能。这时,事件委托就能大显身手!但如果判断条件写错,就无法达到预期效果。

// 获取包含多个列表项的ul元素
const ul = document.querySelector('ul');
// 给ul元素添加点击事件监听
ul.addEventListener('click', function(event) {
// 判断点击的元素是否是li元素(这里错误地使用了class判断,且class名错误)
if (event.target.classList.contains('list-item')) {
console.log('点击了列表项:', event.target.textContent);
}
});

如果列表项中不存在list-item这个 class,上述判断就会失效。正确的做法是根据标签名进行判断。

// 获取包含多个列表项的ul元素
const ul = document.querySelector('ul');
// 给ul元素添加点击事件监听
ul.addEventListener('click', function(event) {
// 判断点击的元素是否是li元素
if (event.target.tagName === 'LI') {
console.log('点击了列表项:', event.target.textContent);
}
});

五、对象合并的「高级技巧」:Object.assign()与展开运算符

在合并多个对象时,Object.assign()和展开运算符都是非常实用的工具。然而,它们也都存在一些容易被忽视的问题。

// 定义两个对象
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
// 使用Object.assign()方法合并对象(这里隐藏错误:会修改原对象)
const mergedObj = Object.assign(obj1, obj2);
// 输出合并后的对象
console.log(mergedObj);
// 输出 { a: 1, b: 3, c: 4 }

Object.assign()是浅拷贝,会直接修改目标对象。如果我们不想影响原对象,可以使用展开运算符。

// 定义两个对象
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
// 使用展开运算符合并对象
const mergedObj = {...obj1,...obj2 };
// 输出合并后的对象
console.log(mergedObj);
// 输出 { a: 1, b: 3, c: 4 },且obj1保持不变

六、URLSearchParams:轻松处理 URL 参数的「利器」

解析和修改 URL 参数时,还在手动拆分和拼接字符串?URLSearchParams能让这些操作变得简单又高效!但如果用错方法,就会事倍功半。

// 创建一个URLSearchParams实例,传入查询字符串
const params = new URLSearchParams('name=Alice&age=25');
// 获取指定参数的值
console.log(params.get('name'));
// 输出 Alice
// 添加新的参数(这里错误地使用了set方法,应使用append方法)
params.set('city', 'Beijing');
// 将参数转换为字符串
console.log(params.toString());

set方法会覆盖已有的同名参数,而我们想要添加新参数,应该使用append方法。

// 创建一个URLSearchParams实例,传入查询字符串
const params = new URLSearchParams('name=Alice&age=25');
// 获取指定参数的值
console.log(params.get('name'));
// 输出 Alice
// 添加新的参数
params.append('city', 'Beijing');
// 将参数转换为字符串
console.log(params.toString());
// 输出 name=Alice&age=25&city=Beijing

七、Array.prototype.find:快速查找数组元素的「宝藏方法」

从数组中查找符合条件的元素,find方法非常方便。但如果使用不当,也可能得不到预期的结果。

// 定义一个包含对象的数组
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 35 }
];
// 使用find方法查找年龄为30的用户(这里错误地使用了全等判断)
const user = users.find(person => person.age === '30');
// 输出查找到的用户(结果为undefined)
console.log(user);

由于数组中age属性的值是数字类型,而我们在判断时使用了字符串,导致查找失败。应使用正确的类型进行比较。

// 定义一个包含对象的数组
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 35 }
];
// 使用find方法查找年龄为30的用户
const user = users.find(person => person.age === 30);
//输出查找到的用户
console.log(user);
// 输出 { name: 'Bob', age: 30 }

以上 7 个 JavaScript 实战技巧里,明面上摆了 3 处明显错误,暗地里还藏着 2 处不易察觉的 “陷阱”!各位 “代码侦探”,快来评论区留言,看看谁能最快把这些错误全部找出来!另外,在实际项目开发中,你更愿意花费时间研究原生 JavaScript 的高级特性,还是直接引入 Lodash 等第三方库来实现相同功能呢?欢迎在评论区分享你的观点,咱们一起讨论!

Tags:

最近发表
标签列表