JavaScript 实用技巧
JavaScript实用技巧:从基础到进阶,提升开发效率
在前端开发中,JavaScript 是交互逻辑核心,简洁的语法技巧能减少冗余代码、规避潜在 Bug。本文会持续更新高频场景的实用技巧,附核心代码与适用场景,可直接落地项目。
快捷目录
- [JavaScript 实用技巧](#JavaScript 实用技巧)
-
- [1. 可选链操作符(`?.`):安全访问嵌套属性](#1. 可选链操作符(
?.):安全访问嵌套属性) - [2. 空值合并赋值(`??=`):精准设置默认值](#2. 空值合并赋值(
??=):精准设置默认值) - [3. `Intl` 对象:本地化格式化(货币/日期)](#3.
Intl对象:本地化格式化(货币/日期)) -
- [3.1 货币格式化](#3.1 货币格式化)
- [3.2 日期时间格式化](#3.2 日期时间格式化)
- [4. `Promise.allSettled()`:批量异步请求不中断](#4.
Promise.allSettled():批量异步请求不中断) - [5. 数组去重:`[...new Set(arr)]` 一行实现](#5. 数组去重:
[...new Set(arr)]一行实现) - [6. 解构赋值:快速提取对象/数组数据](#6. 解构赋值:快速提取对象/数组数据)
-
- [6.1 对象解构](#6.1 对象解构)
- [6.2 数组解构](#6.2 数组解构)
- [7. 数组扁平化:`flat()` 替代递归](#7. 数组扁平化:
flat()替代递归) - [8. 短路求值:`&&`/`||` 简化条件判断](#8. 短路求值:
&&/||简化条件判断) - [9. 对象浅拷贝:`{...obj}`/`Object.assign()`](#9. 对象浅拷贝:
{...obj}/Object.assign()) - [10. `async/await` 错误处理:`try/catch`/`.catch()`](#10.
async/await错误处理:try/catch/.catch()) -
- 单个请求处理
- [批量请求处理(配合 `Promise.allSettled`)](#批量请求处理(配合
Promise.allSettled))
- 总结
- [1. 可选链操作符(`?.`):安全访问嵌套属性](#1. 可选链操作符(
1. 可选链操作符(?.):安全访问嵌套属性
解决嵌套属性访问报错问题,左侧为 null/undefined 时返回 undefined,不抛错。
js
// 传统写法:层层判断
const city = user && user.address && user.address.city;
// 技巧写法:简化判断
const city = user?.address?.city;
适用场景 :访问后端不确定结构数据、DOM 元素属性(如 document.querySelector('.btn')?.textContent)。
2. 空值合并赋值(??=):精准设置默认值
仅当属性为 null/undefined 时赋值,不覆盖非空值(如 0、''、false)。
js
// 传统写法:手动判断
if (object.retries === null || object.retries === undefined) {
object.retries = 3;
}
// 技巧写法:一步到位
object.retries ??= 3;
适用场景:初始化配置项(请求重试次数)、函数参数默认值。
3. Intl 对象:本地化格式化(货币/日期)
原生 API 实现多地区格式化,无需第三方库。
3.1 货币格式化
自动添加货币符号与千分位:
js
// 人民币(¥12,345.67)
const cnyPrice = new Intl.NumberFormat('zh-CN', {
style: 'currency', currency: 'CNY'
}).format(12345.67);
// 美元($12,345.67)
const usdPrice = new Intl.NumberFormat('en-US', {
style: 'currency', currency: 'USD'
}).format(12345.67);
3.2 日期时间格式化
适配地区习惯,无需手动拼接字段:
js
// 中文日期(2024年10月26日 14:30:45)
const cnDate = new Intl.DateTimeFormat('zh-CN', {
year: 'numeric', month: 'long', day: 'numeric',
hour: '2-digit', minute: '2-digit', second: '2-digit'
}).format(new Date());
适用场景:电商价格展示、日志时间、多语言项目本地化。
4. Promise.allSettled():批量异步请求不中断
等待所有请求结束(成功/失败),返回每个请求状态,不因单个失败中断。
js
const requests = [fetch('/api/user'), fetch('/api/orders'), fetch('/api/products')];
const results = await Promise.allSettled(requests);
// 处理结果
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`请求${index+1}成功:`, await result.value.json());
} else {
console.error(`请求${index+1}失败:`, result.reason);
}
});
适用场景:仪表盘多模块数据加载、批量数据同步(需完整结果)。
5. 数组去重:[...new Set(arr)] 一行实现
基于 Set 不重复特性,简洁高效(适用于基本类型)。
js
// 传统写法:filter + indexOf
const uniqueArr = arr.filter((item, i) => arr.indexOf(item) === i);
// 技巧写法:Set + 扩展运算符
const uniqueArr = [...new Set(arr)]; // 例:[1,2,2,3] → [1,2,3]
对象数组去重 :搭配 Map 提取唯一键(如 id):
js
const uniqueObjArr = [...new Map(objArr.map(item => [item.id, item])).values()];
6. 解构赋值:快速提取对象/数组数据
批量提取数据,替代逐个赋值。
6.1 对象解构
js
const user = { name: '张三', age: 25, address: '北京' };
// 基础提取
const { name, age } = user;
// 重命名 + 默认值
const { name: userName, address = '未知地址' } = user;
6.2 数组解构
js
const arr = [10, 20, 30, 40];
// 按位置提取
const [first, second] = arr;
// 跳过元素 + 剩余元素
const [, , third, ...rest] = arr; // third=30, rest=[40]
适用场景 :提取接口数据、函数参数传递、交换变量([a,b] = [b,a])。
7. 数组扁平化:flat() 替代递归
一键展平嵌套数组,支持自定义深度。
js
const nestedArr = [1, [2, [3, [4]]]];
// 展平所有层级
const flatAll = nestedArr.flat(Infinity); // [1,2,3,4]
// 展平1层
const flatOne = nestedArr.flat(1); // [1,2,[3,[4]]]
// 兼容旧环境:reduce + concat
const flatArr = nestedArr.reduce((acc, item) =>
acc.concat(Array.isArray(item) ? flatArr(item) : item), []);
8. 短路求值:&&/|| 简化条件判断
利用逻辑运算符短路特性,替代简单 if-else。
js
// ||:取第一个真值(设置默认值)
const title = data.title || '默认标题';
// &&:条件成立执行逻辑
user.isLogin && showUserMenu();
注意 :|| 会过滤 0/'',需保留这些值时用 ??。
9. 对象浅拷贝:{...obj}/Object.assign()
避免引用传递,复制第一层属性(嵌套属性仍为引用)。
js
const oldObj = { name: '张三', address: { city: '北京' } };
// 扩展运算符(简洁)
const newObj1 = { ...oldObj };
// Object.assign()
const newObj2 = Object.assign({}, oldObj);
// 深拷贝:简单场景用 JSON.parse(JSON.stringify(oldObj)),复杂场景用 lodash.cloneDeep()
10. async/await 错误处理:try/catch/.catch()
优雅处理异步错误,避免报错中断流程。
单个请求处理
js
async function fetchUser() {
try {
const res = await fetch('/api/user');
return await res.json();
} catch (err) {
console.error('请求失败:', err);
return null;
}
}
批量请求处理(配合 Promise.allSettled)
js
async function fetchBatchData() {
const results = await Promise.allSettled([fetch('/api/user'), fetch('/api/orders')]);
const successData = results.filter(r => r.status === 'fulfilled').map(r => r.value.json());
const failReasons = results.filter(r => r.status === 'rejected').map(r => r.reason);
return { successData, failReasons };
}
总结
以上技巧聚焦 "属性访问安全""格式化效率""异步稳定性" 等开发痛点,核心是用简洁语法解决实际问题。好的 JavaScript 代码,在于用最简单的方式实现需求。