会直接修改原数组的方法有push()、pop()、shift()、unshift()、splice()、sort()、reverse()、fill()和copyWithin();filter/map/reduce均返回新数组;find/findIndex/includes/indexOf适用于不同查找场景;for...of支持中断,forEach不支持。
JavaScript 数组操作的核心不是背方法列表,而是理解哪些方法会改原数组、哪些返回新数组、哪些适合遍历、哪些适合查找——选错方法会导致隐性 bug 或性能浪费。
这类方法副作用明显,容易在不经意间破坏数据源,尤其在 React/Vue 等响应式场景中引发渲染异常。
push()、pop()、shift()、unshift():增删首尾元素,返回新长度或被删元素splice():万能修改器,可删、可插、可替,返回被删除的元素数组sort():默认按字符串 Unicode 排序,[10, 2, 30].sort() 得到 [10, 2, 30](不是 [2, 10, 30]),必须传比较函数:arr.sort((a, b) => a - b)
reverse():就地翻转,不返回新数组⚠️ 注意:fill() 和 copyWithin() 也改原数组,但使用频率低,容易被忽略其副作用。
这三个是函数式编程主力,都返回新数组(不改原数组),但语义和用途截然不同。
filter():筛选。只保留满足条件的元素,返回等长或更短的新数组。例如:[1,2,3,4].filter(x => x % 2 === 0) → [2, 4]
map():转换。每个元素按规则映射为新值,返回等长新数组。例如:['a','b'].map(x => x.toUpperCase()) → ['A','B']
reduce():聚合。把数组“压成”一个值(可以是对象、数字、字符串甚至新数组)。例如:[1,2,3].reduce((sum, x) => sum + x, 0) → 6;想扁平化二维数组?arr.reduce((acc, row) => acc.concat(row), [])
别用 map() 做筛选(会留下 undefined),也别用 filter() 做转换(无法改结构)。
都是查找类方

find():返回第一个满足条件的元素值,没找到返回 undefined
findIndex():返回第一个满足条件的索引,没找到返回 -1
includes():返回 true/false,支持 NaN 检测(indexOf() 对 NaN 返回 -1)indexOf():返回首次出现的索引,严格相等(===),对 NaN 失效查是否存在用 includes() 最安全;要拿元素本身用 find();要改该位置的值,得先 findIndex() 再赋值。
两者都用于遍历,但控制流能力完全不同,不能简单互换。
for...of:原生语法,支持 break、continue、return(在函数内),可中断循环forEach():是方法调用,不支持 break 或 return 中断(return 只退出当前回调,不影响后续迭代)需要提前退出(比如找到目标就停)、或需要捕获异常并 continue,必须用 for...of。仅做无条件遍历且逻辑简单时,forEach() 可读性略高。
const arr = [1, 2, 3, 4, 5];
// ✅ 正确:可中断
for (const item of arr) {
if (item === 3) break;
console.log(item); // 输出 1, 2
}
// ❌ 无效:return 不会中断 forEach
arr.forEach(item => {
if (item === 3) return; // 下面的 log 还是会执行 4 和 5
console.log(item);
});
真正容易被忽略的是:所有高阶方法(map、filter 等)内部都创建新数组,大数据量时内存开销明显;而 for 或 for...of 是零分配。性能敏感场景别无脑链式调用。