前端开发总踩坑?5 个 JavaScript 实战技巧让你少写 30% 冗余代码

前端圈最近都在聊性能优化、代码复用,说实话,写 JavaScript 代码时,谁还没踩过几个 “坑”?数据加载慢、逻辑混乱、调试到崩溃…… 别慌!今天分享 5 个超实用的实战技巧,全是从项目里摸爬滚打总结出来的,帮你直击痛点,少写 30% 冗余代码!

一、数据请求超时处理:告别 “加载转圈” 的尴尬

你可能会发现,在做页面数据请求时,偶尔会遇到接口迟迟没响应,页面一直转圈圈,用户体验直接拉胯。这时候,给请求加个 “限时令” 就很有必要!

// 封装一个带超时的fetch请求函数
function timeoutFetch(url, options = {}, timeout = 5000) {
return Promise.race([
// 发起正常的fetch请求
fetch(url, options),
// 延迟timeout时间后,抛出超时错误
new Promise((_, reject) => setTimeout(() => reject(new Error('请求超时')), timeout))
]);
}
// 使用带超时的fetch请求
timeoutFetch('https://example.com/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

这里用Promise.race同时发起请求和定时器,谁先完成就用谁的结果。要是定时器先跑完,直接报错,再也不怕用户对着空白页干瞪眼!在电商项目中处理商品列表加载,用上这个,页面响应速度肉眼可见提升。

二、对象属性克隆:防止 “牵一发而动全身” 的修改

当你需要修改对象属性,但又怕影响原始数据时,直接赋值可不行!举个例子,直接const newObj = oldObj,改newObj里的值,oldObj也跟着变,这就出大问题了!

// 浅克隆对象(只克隆一层属性)
const shallowClone = (obj) => ({...obj });
// 定义原始对象
const original = { name: 'Alice', age: 25, address: { city: 'New York' } };
// 进行浅克隆
const cloned = shallowClone(original);
// 修改克隆对象的属性
cloned.age = 26;
// 输出: {name: "Alice", age: 26, address: {city: "New York"}}
console.log(cloned);
// 原始对象的age属性未变
// 输出: {name: "Alice", age: 25, address: {city: "New York"}}
console.log(original);
// 深克隆对象(递归克隆多层嵌套属性)
function deepClone(obj) {
if (typeof obj!== 'object' || obj === null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(deepClone);
}
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, deepClone(value)]));
}
// 进行深克隆
const deeplyCloned = deepClone(original);
// 修改深克隆对象嵌套属性
deeplyCloned.address.city = 'Los Angeles';
// 输出: {name: "Alice", age: 25, address: {city: "Los Angeles"}}
console.log(deeplyCloned);
// 原始对象的address.city属性未变
// 输出: {name: "Alice", age: 25, address: {city: "New York"}}
console.log(original);

浅克隆适合单层对象,深克隆应对复杂嵌套数据。在处理用户表单数据缓存时,克隆一份再修改,能避免很多莫名其妙的 bug,是不是很神奇?

三、数组快速筛选:filter结合includes的神仙组合

从一堆数据里找出符合条件的元素,你还在循环遍历一个个对比?filter和includes搭配,直接起飞!

// 定义一个水果数组
const fruits = ['苹果', '香蕉', '橘子', '葡萄', '草莓'];
// 定义要筛选的水果类型
const selectedFruits = ['苹果', '葡萄'];
// 使用filter和includes筛选出符合条件的水果
const filteredFruits = fruits.filter(fruit => selectedFruits.includes(fruit));
// 输出: ["苹果", "葡萄"]
console.log(filteredFruits);

这招在处理用户勾选列表、权限筛选等场景超实用。之前做后台管理系统的菜单权限,用这两行代码,瞬间筛选出用户有权限的菜单,效率翻倍!

四、函数柯里化:让代码更 “灵活” 的魔法

有时候函数参数太多,用起来不够灵活?函数柯里化了解一下!

// 柯里化函数示例,将多参数函数转化为单参数函数链
function add(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
// 使用柯里化函数
const result = add(1)(2)(3);
// 输出: 6
console.log(result);

柯里化能把多参数函数拆成一个个单参数函数,用的时候更灵活。比如封装一个计算折扣的函数,先固定折扣率,再传入原价,代码复用性直接拉满!

五、浏览器存储管理:localStorage和sessionStorage的正确打开方式

用localStorage和sessionStorage存数据,结果取出来是字符串,类型全乱套?这就涉及到一个关键点 —— 数据存取的正确姿势!

// 存储对象到localStorage(需要先转为JSON字符串)
const userData = { name: 'Bob', age: 30 };
localStorage.setItem('user', JSON.stringify(userData));
// 从localStorage取出数据(需要转为原始对象)
const retrievedData = JSON.parse(localStorage.getItem('user'));
// 输出: {name: "Bob", age: 30}
console.log(retrievedData);
// 清除localStorage中的数据
localStorage.removeItem('user');

记住存数据用JSON.stringify转字符串,取数据用JSON.parse还原。在做用户偏好设置存储时,规范使用这两个方法,能少掉 90% 的类型错误!

看完这些技巧,是不是感觉打开了新世界?最后留个讨论话题:在实际开发中,你觉得哪个 JavaScript 技巧最能提升效率?是处理数据的,还是优化性能的?欢迎在评论区 “Battle”,分享你的实战经验!