一、先分类:改不改原数组
| 不改原数组(返回新值) | 会改原数组 |
|---|---|
map filter slice concat flat flatMap | push pop shift unshift splice sort reverse fill |
find findIndex some every includes indexOf | copyWithin |
记忆法:slice(切片)不改,splice(拼接/删除)改。sort 和 reverse 是原地操作,这一点最容易被忽略——共享引用时会把别处的数据也改了。
二、五个最常用的
const users = [{id:1,name:'A',age:20},{id:2,name:'B',age:30}];
users.map(u => u.name); // ['A','B'] 映射
users.filter(u => u.age > 25); // [{id:2,...}] 筛选
users.find(u => u.id === 2); // {id:2,...} 找第一个
users.some(u => u.age > 25); // true 存在
users.every(u => u.age > 25); // false 全部满足
users.reduce((sum, u) => sum + u.age, 0); // 50 累计
区别要点:
map返回等长数组,不筛元素。filter返回子集,长度可变。find返回元素本身,找不到是undefined;findIndex返回索引,找不到是-1。some/every返回布尔值,且短路(找到就停)。reduce最灵活,能做求和、分组、去重、扁平化。
三、reduce 的两种用法
// 求和
[1,2,3].reduce((a, b) => a + b, 0); // 6
// 按字段分组
users.reduce((acc, u) => {
(acc[u.city] = acc[u.city] || []).push(u);
return acc;
}, {});
第二个参数(初始值)一定要给。不给时,空数组会抛 TypeError: Reduce of empty array with no initial value,且对象数组会以第一个元素为初始值,容易算错。
四、sort 的三个坑
[10, 9, 1].sort(); // [1, 10, 9] ← 按字符串比较
[10, 9, 1].sort((a, b) => a - b); // [1, 9, 10] ← 正确
[...arr].sort((a, b) => a - b); // 不改原数组的写法
- 默认转字符串按 Unicode 码点排序,数字会乱。
- 比较函数必须返回数字(负数/0/正数),返回布尔值不会报错但结果不可靠。
- 排序不稳定是历史问题,现代引擎已保证稳定(相同键保持原顺序),但不要依赖它做业务排序。
对象排序:
list.sort((a, b) => a.age - b.age);
list.sort((a, b) => a.name.localeCompare(b.name, 'zh-CN')); // 中文按拼音
localeCompare 比 > 更适合字符串比较,能正确处理中文、大小写和重音符号。
五、includes 与 indexOf 的差别
[1, 2, NaN].includes(NaN); // true
[1, 2, NaN].indexOf(NaN); // -1 ← NaN !== NaN
includes 用 SameValueZero 比较,能正确判断 NaN;indexOf 用严格相等,找不到 NaN。判断存在性优先 includes。
六、几个实用的新方法
flat(depth):拍平数组,flat(Infinity)全拍平。flatMap(fn):先 map 再 flat 一层,比map().flat()少一次遍历。at(-1):取最后一个元素,比arr[arr.length - 1]简洁。Array.from({length: 5}, (_, i) => i):生成[0,1,2,3,4]。Object.groupBy(arr, fn):按条件分组(较新,需确认目标环境)。
七、性能与可读性
链式调用 map().filter().map() 会创建多个中间数组,数据量大时(十万级以上)有明显开销。此时用一次 reduce 或 for 循环更快。但不要过早优化:绝大多数业务数据在几百条以内,可读性优先。
需要格式化和检查代码时,用 代码格式化;处理接口返回的数组结构时,用 JSON 格式化校验 先看清层级。
小结
map/filter/slice 不改原数组,sort/splice/reverse 会改;sort 数字要传比较函数;reduce 记得给初始值;判断存在用 includes。