苟日新,日日新,又日新
... 数组扩展运算符| 场景 | 代码 | 说明 |
|---|---|---|
| 数据转换 | [1,2,3].map(x => x * 2) // [2,4,6] |
映射转换每个元素 |
| 对象转换 | arr.map(obj => obj.name) |
提取对象属性 |
| 组合操作 | users.map(u => ({...u, age: u.age+1})) |
返回新对象 |
| 链式调用 | arr.map(x => x*2).map(x => x+1) |
方法链式使用 |
| 注意问题 | 说明 |
|---|---|
| 不修改原数组 | 返回新数组,原数组不变 |
| 长度一致 | 返回数组长度与原数组相同 |
| 空位保留 | 会跳过空位(稀疏数组) |
| 场景 | 代码 | 说明 |
|---|---|---|
| 条件筛选 | [1,2,3,4].filter(x => x > 2) // [3,4] |
返回符合条件的元素 |
| 去除空值 | arr.filter(Boolean) |
过滤 false、0、空字符串等 |
| 对象筛选 | users.filter(u => u.active) |
筛选对象数组 |
| 多重条件 | arr.filter(x => x > 0 && x < 10) |
多条件组合过滤 |
| 注意问题 | 说明 |
|---|---|
| 不修改原数组 | 返回新数组,原数组不变 |
| 返回长度不定 | 返回数组长度可能小于原数组 |
| 空位跳过 | 会跳过稀疏数组的空位 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 求和汇总 | [1,2,3].reduce((a,b) => a+b) // 6 |
累加求和 |
| 对象统计 | arr.reduce((m, o) => {m[o.id]++; return m}, {}) |
分组统计 |
| 数组扁平化 | arr.reduce((a, b) => [...a, ...b], []) |
手动扁平化 |
| 从右向左 | arr.reduceRight(...) |
ES3,从右到左遍历 |
| 注意问题 | 说明 |
|---|---|
| 需要初始值 | 不提供初始值时从索引1开始 |
| 首次回调参数 | 无初始值时第一个值是 arr[0] |
| reduceRight 已弃用 | 现代开发较少使用 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 简单遍历 | arr.forEach(x => console.log(x)) |
无返回值的遍历 |
| 修改外部变量 | let sum = 0; arr.forEach(x => sum += x) |
累加外部变量 |
| 对象遍历 | arr.forEach((item, i, a) => {}) |
提供索引和原数组 |
| 链式中断 | arr.forEach(x => {if(x<0) return}) |
无法提前跳出 |
| 注意问题 | 说明 |
|---|---|
| 无返回值 | 总是返回 undefined |
| 不可中断 | 无法用 break 提前结束 |
| 不跳过空位 | 会遍历到空位并调用回调 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 查找元素 | [1,2,3,4].find(x => x > 2) // 3 |
返回第一个匹配元素 |
| 查找索引 | [1,2,3,4].findIndex(x => x > 2) // 2 |
返回第一个匹配索引 |
| 对象查找 | users.find(u => u.id === 1) |
查找对象数组元素 |
| 未找到返回 | arr.find(x => false) // undefined |
未匹配返回 undefined |
| 注意问题 | 说明 |
|---|---|
| 第一个匹配 | findIndex 找第一个索引 |
| 空位跳过 | 会跳过稀疏数组空位 |
| 不修改原数组 | 只读取不修改 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 扁平化一层 | [[1]].flat() // [1,2,3,4] |
展开一层嵌套 |
| 扁平化多层 | arr.flat(2) |
指定展开深度 |
| 移除空位 | [1,2,,4].flat() // [1,2,4] |
自动移除空位 |
| 映射+扁平 | arr.flatMap(fn) |
ES2019 组合操作 |
| 注意问题 | 说明 |
|---|---|
| flat 不递归 | flat(Infinity) 也不递归无限深 |
| flatMap 只一层 | flatMap 等价于 map + flat(1) |
| 空位移除 | 会自动移除数组空位 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 存在判断 | [1,2,3].includes(2) // true |
ES2016 新增,布尔值 |
| 精确匹配 | [1,2,3].includes(NaN) // true |
NaN 也能匹配 |
| 查找索引 | [1,2,3].indexOf(2) // 1 |
返回第一个索引 |
| 从后查找 | [1,2,3].lastIndexOf(2) // 1 |
从末尾向左找 |
| 注意问题 | 说明 |
|---|---|
| includes 更可靠 | includes 能正确匹配 NaN |
| indexOf 不支持 | indexOf 找不到 NaN 索引 |
| 从0开始 | 索引从 0 开始计算 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 全部满足 | [1,2,3].every(x => x > 0) // true |
全部元素满足条件 |
| 部分满足 | [1,-2,3].some(x => x < 0) // true |
至少一个满足条件 |
| 对象验证 | users.every(u => u.active) |
验证对象数组 |
| 短路返回 | every() 遇到 false 就停 | 找到不符合立即返回 |
| 注意问题 | 说明 |
|---|---|
| 布尔返回值 | 都返回布尔值结果 |
| 空数组结果 | empty.every() 返回 true, some() 返回 false |
| 跳过空位 | 会跳过稀疏数组空位 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 正向索引 | arr.at(0) // 第一个元素 |
ES2022 新增 |
| 负向索引 | arr.at(-1) // 最后一个元素 |
支持负数索引 |
| 安全访问 | arr.at(-100) // undefined |
越界返回 undefined |
| 替代长度 | arr[arr.length-1] |
简化代码 |
| 注意问题 | 说明 |
|---|---|
| 较新特性 | 需较新浏览器支持 |
| 越界安全 | 不抛出错误,返回 undefined |
| 仅访问 | 仅用于读取,不能修改 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 数字排序 | [3,1,2].sort((a,b) => a-b) // [1,2,3] |
自定义比较函数 |
| 字母排序 | ['c','a','b'].sort() // ['a','b','c'] |
默认按字符串排序 |
| 不可变排序 | [3,1,2].toSorted() // [1,2,3] |
ES2023 不修改原数组 |
| 降序排序 | arr.sort((a,b) => b-a) |
反向排序 |
| 注意问题 | 说明 |
|---|---|
| sort 会修改 | 常规 sort() 会修改原数组 |
| 默认排序 | 默认排序按字符串,数字会错 |
| toSorted 新增 | ES2023 新增,推荐优先使用 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 截取数组 | [1,2,3,4].slice(1,3) // [2,3] |
不包含结束索引 |
| 复制数组 | [1,2,3].slice() // 新数组 |
浅拷贝数组 |
| 从后截取 | arr.slice(-2) |
负数表示从后 |
| 替换元素 | [1,2,3].splice(1,1,4) // [2] |
删除并替换元素 |
| 注意问题 | 说明 |
|---|---|
| slice 不修改 | slice 返回新数组,不修改原数组 |
| splice 会修改 | splice 会修改原数组 |
| splice 返回值 | 返回被删除的元素数组 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 数组合并 | [1,2].concat([3,4]) // [1,2,3,4] |
合并多个数组 |
| 添加元素 | [1,2].concat(3) // [1,2,3] |
添加单个值 |
| 展开合并 | arr1.concat(...arr2) |
展开数组合并 |
| 链式合并 | [1].concat([2]).concat([3]) |
连续合并多个 |
| 注意问题 | 说明 |
|---|---|
| 不修改原数组 | 返回新数组 |
| 浅拷贝 | 只拷贝引用,不深拷贝 |
| 现代写法 | 推荐 […a, …b] 语法 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 数组转字符串 | [1,2,3].join('-') // "1-2-3" |
自定义分隔符 |
| CSV 格式 | arr.join(',') |
生成逗号分隔值 |
| 默认转串 | arr.toString() // "1,2,3" |
默认逗号分隔 |
| 本地化格式 | arr.toLocaleString() |
遵循地区格式 |
| 注意问题 | 说明 |
|---|---|
| join 可定制 | 可指定任意分隔符 |
| toString 固定 | 总是用逗号分隔 |
| toLocale 地区 | 数字按地区格式化 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 尾部添加 | arr.push(1,2,3) |
返回新长度 |
| 尾部删除 | arr.pop() |
返回被删除元素 |
| 头部删除 | arr.shift() |
移除第一个元素 |
| 头部添加 | arr.unshift(1,2) |
返回新长度 |
| 注意问题 | 说明 |
|---|---|
| 会修改原数组 | 四种方法都会修改原数组 |
| pop/shift 快 | 头尾操作比中间快 |
| shift/unshift 慢 | 头部操作会影响所有索引 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 反转数组 | [1,2,3].reverse() // [3,2,1] |
修改原数组 |
| 不可变反转 | [1,2,3].toReversed() // [3,2,1] |
ES2023 新数组 |
| 字符串反转 | str.split('').reverse().join('') |
反转字符串 |
| 多次反转 | arr.toReversed().toReversed() // 原数组 |
两次回到原位 |
| 注意问题 | 说明 |
|---|---|
| reverse 会修改 | 常规 reverse() 修改原数组 |
| toReversed 新增 | ES2023 新增,不修改原数组 |
| 元素引用 | 浅拷贝,对象仍是引用 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 替换元素 | arr.with(0, 100) |
ES2023 新特性 |
| 负数索引 | arr.with(-1, 200) |
支持负索引 |
| 链式操作 | arr.with(0,1).with(1,2) |
链式替换 |
| 不可变操作 | arr.with(i, x) |
不修改原数组 |
| 注意问题 | 说明 |
|---|---|
| 较新特性 | ES2023 新增,需新浏览器 |
| 单元素操作 | 一次只能替换一个元素 |
| 不可变 | 返回新数组,不修改原数组 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 反向查找 | [1,2,3,4].findLast(x => x > 2) // 4 |
ES2023 从末尾找 |
| 反向索引 | [1,2,3,4].findLastIndex(x => x > 2) // 3 |
返回索引 |
| 对象查找 | arr.findLast(item => item.active) |
查找最后一个匹配对象 |
| 未找到返回 | arr.findLast(x => false) // undefined |
未匹配返回 undefined |
| 注意问题 | 说明 |
|---|---|
| 较新特性 | ES2023 新增 |
| 从后向前 | 从数组末尾开始查找 |
| 空位跳过 | 会跳过空位 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 插入元素 | [1,2,3].toSpliced(1,0,99) // [1,99,2,3] |
ES2023 在指定位置插入 |
| 删除元素 | arr.toSpliced(1,1) // 删除一个 |
删除指定数量 |
| 替换元素 | arr.toSpliced(1,1,200) // 替换一个 |
删除并替换 |
| 不可变操作 | 不修改原数组 | 返回新数组 |
| 注意问题 | 说明 |
|---|---|
| 较新特性 | ES2023 新增 |
| 参数含义 | (index, deleteCount, …items) |
| 不修改原数组 | 返回新数组 |
| 场景 | 代码 | 说明 |
|---|---|---|
| 创建数组 | Array.of(1,2,3) // [1,2,3] |
ES2015 替代 new Array |
| 单参数创建 | Array.of(5) // [5] |
不会创建长度为5的空数组 |
| 类型判断 | Array.isArray([1,2,3]) // true |
可靠判断数组 |
| 继承判断 | Array.isArray(obj) // false |
判断对象 |
| 注意问题 | 说明 |
|---|---|
| 单参数安全 | Array.of(5) 不会创建空数组 |
| new Array 陷阱 | new Array(5) 创建空数组 |
| 类型判断 | 最可靠的数组判断方法 |
... 数组扩展运算符| 场景 | 代码 | 说明 |
|---|---|---|
| 展开数组 | [...[1,2,3]] // [1,2,3] |
展开数组 |
| 合并数组 | [...a, ...b] // [a,b 合并] |
合并多个数组 |
| 复制数组 | [...arr] // 新数组 |
浅拷贝数组 |
| 函数参数 | fn(...arr) |
数组转参数 |
| 注意问题 | 说明 |
|---|---|
| 浅拷贝 | 只复制第一层 |
| 不可变操作 | 不会修改原数组 |
| 现代语法 | 推荐优先使用 |