JavaScript数组方法分mutate(如push、splice)和immutable(如map、filter)两类,需据是否修改原数组及是否需新数组选择;误用易致React重渲染失败等bug。
mutate 还是 return new array
JavaScript 数组方法分两类:一类直接修改原数组(mutate),另一类返回新数组(immutable)。混淆这两类是 bug 高发区,比如在 React 中误用 push() 后没触发重渲染,或用 filter() 却忘了接返回值。
mutate 方法: push()、pop()、shift()、unshift()、splice()、sort()、reverse()
immutable 方法: map()、filter()、slice()、concat()、flat()、toSorted()(ES2025)、with()(ES2025)forEach() 不改变原数组,也不返回新数组(返回 undefined),别拿来赋值splice() 怎么安全删/插/替 —— 参数顺序和返回值容易错splice() 是唯一能同时删除、插入、替换的原地操作方法,但参数顺序反直觉:第一个是起始索引,第二个是删除个数,之后才是插入项。它还会返回被删元素组成的数组,不是原数组。
const arr = ['a', 'b', 'c', 'd']; arr.splice(1, 2, 'x', 'y'); // 从索引1开始删2个 → ['b','c'],插入'x','y' console.log(arr); // ['a', 'x', 'y', 'd'] console.log(spliceResult); // ['b', 'c'] ← 别漏了这个返回值
splice(start, deleteCount),如 arr.splice(-1, 1) 删末尾splice(start, 0, ...items),第二个参数必须是 0
toSpliced()(ES2025),它返回新数组,不改原数组map() 和 forEach() 什么时候不能互换两者都遍历,但语义完全不同:map() 是“转换”,必须有返回值且生成新数组;forEach() 是“执行副作用”,比如发请求、改 DOM、累加变量,没有返回值(undefined)。
const nums = [1, 2, 3]; const doubled = nums.map(x => x * 2); // [2, 4, 6] const ignored = nums.forEach(x => console.log(x * 2)); // 打印 2 4 6,ignored 是 undefined
map() 却没 return?结果数组全是 undefined
forEach() 想构造新数组?得手动 push(),不如直接用 map()
break,改用 for...of 或 some()/every()
flat() 的深度和空位处理flat() 默认只展开一层,遇到多层嵌套要传深度参数;它还会自动过滤掉空槽(empty),这点常被忽略。
const arr = [1, [2, [3, 4]], 5]; arr.flat(); // [1, 2, [3, 4], 5] arr.flat(2); // [1, 2, 3, 4, 5] arr.flat(Infinity); // 同上,彻底展平 const sparse = [1, , 3]; // 空槽 sparse.flat(); // [1, 3] ← 空槽被移除了
flat(),改用 flatMap() + 显式返回或 reduce()
flat()?用 reduce((acc, val) => acc.concat(Array.isArray(val) ? val : [val]), [])
flattenDeep()
有些方法看着像,行为却隔着一层语义墙;比如 sort() 默认按字符串排序
,includes() 用 SameValueZero 比较,findIndex() 找不到返回 -1 而不是 undefined —— 这些细节不翻 MDN 容易踩进静默陷阱。