🔥JavaScript 数组全解析:从「到底是不是数组?」到「方法全家桶」一篇搞定

"把数组玩透,才能把前端写活。"

本文首发于作者博客,持续更新,建议收藏。


目录

  1. 判断:我到底是不是数组?
  2. 静态方法:不需要实例就能用的工具箱
  3. 会改变原数组的方法(9 个)
  4. 不会改变原数组的方法(10+ 个)
  5. ES2023+ 的新玩具:toSorted / toReversed / toSpliced
  6. 高频手写题 & 易错点
  7. 一张思维导图带走全部记忆

1. 判断:到底是不是数组?

方式 代码 结果 说明
instanceof [] instanceof Array ✅ true 只能判断「由 Array 构造函数创建」的对象
Array.isArray Array.isArray([]) ✅ true 推荐!能识别 iframe / window 跨上下文
Object.prototype.toString Object.prototype.toString.call([]) [object Array] 通用,可区分 Array, Arguments, NodeList
constructor [].constructor === Array ✅ true 可伪造,不安全

结论:生产环境统一用 Array.isArray,面试题再补 toString 彰显深度。


2. 静态方法

方法 作用 示例
Array.from 类数组 / 可迭代 → 真数组 Array.from({length:3}, (_,i)=>i) // [0,1,2]
Array.of 避免 new Array(3) 的坑 Array.of(3) // [3]
Array.isArray 见第 1 节

3. 会改变原数组的方法(9 个)

口诀:「推(push) 波(pop) 前(shift) 后(unshift) 排(sort) 反(reverse) 切(splice) 填(fill) 拷(copyWithin)

方法 作用 返回 示例
push 尾部追加 新长度 arr.push(4)
pop 尾部删除 被删元素 arr.pop()
shift 头部删除 被删元素 arr.shift()
unshift 头部追加 新长度 arr.unshift(0)
splice 万能增删改 被删数组 arr.splice(1,2,'x','y')
sort 字典序排序 原数组 arr.sort((a,b)=>a-b)
reverse 反转 原数组 arr.reverse()
fill 填充 原数组 new Array(5).fill(0)
copyWithin 内部拷贝 原数组 [1,2,3,4].copyWithin(0,2)[3,4,3,4]

4. 不会改变原数组的方法

4.1 查询 & 过滤

  • includes (ES2016)
  • indexOf / lastIndexOf
  • find / findIndex / findLast(ES2022)
  • filter

4.2 转换

  • map
  • flat / flatMap (ES2019)

4.3 归约

  • reduce / reduceRight

4.4 遍历

  • forEach(注意:无法 break

4.5 切片

  • slice(start?, end?)

4.6 连接

  • concat

4.7 字符串化

  • join

5. ES2023+ 新玩具:非变异版本

新方法 语义 与原方法关系
toSorted 排序 返回新数组,同 slice().sort()
toReversed 反转 返回新数组
toSpliced 增删改 返回新数组
with(index, value) 替换单元素 函数式写法

有了它们,React 状态更新再也不用手动 ...arr 拷贝。


6. 高频手写题 & 易错点

6.1 手写 flat

js 复制代码
function flat(arr, depth = 1) {
  return depth > 0
    ? arr.reduce((acc, cur) => acc.concat(Array.isArray(cur) ? flat(cur, depth - 1) : cur), [])
    : arr.slice();
}

6.2 不要信任 sort 的稳定性

  • Chrome v8 在数组长度 ≤ 10 时插入排序,>10 时快排 → 老版本不稳定
  • 解决:arr.map((v,i)=>({v,i})).sort((a,b)=>a.v-b.v||a.i-b.i).map(o=>o.v)

6.3 稀疏数组的坑

js 复制代码
new Array(3).map(() => 1) // [empty × 3]  不会执行
[,,,].forEach(console.log) // 无输出

改用 Array.from({length:3}, () => 1)


7. 思维导图(文字版)

perl 复制代码
Array
├─ 判断
│  ├─ Array.isArray
│  └─ Object.prototype.toString
├─ 静态方法
│  ├─ Array.from
│  └─ Array.of
├─ 改变自身
│  ├─ push / pop / shift / unshift
│  ├─ splice / sort / reverse
│  └─ fill / copyWithin
├─ 不改变自身
│  ├─ 查询:includes find filter ...
│  ├─ 转换:map flat flatMap
│  ├─ 归约:reduce reduceRight
│  └─ 工具:slice join concat
└─ ES2023+
   ├─ toSorted / toReversed / toSpliced
   └─ with

结语

数组方法虽多,但记住「是否改变原数组」这条主线,再结合实际场景(React 状态不可变、算法题手写等),即可 掌握全部精髓。

相关推荐
前端老宋Running7 分钟前
一次从“卡顿地狱”到“丝般顺滑”的 React 搜索优化实战
前端·react.js·掘金日报
隔壁的大叔7 分钟前
如何自己构建一个Markdown增量渲染器
前端·javascript
用户4445543654269 分钟前
Android的自定义View
前端
WILLF10 分钟前
HTML iframe 标签
前端·javascript
枫,为落叶27 分钟前
Axios使用教程(一)
前端
小章鱼学前端32 分钟前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
ohyeah33 分钟前
JavaScript 词法作用域、作用域链与闭包:从代码看机制
前端·javascript
流星稍逝35 分钟前
手搓一个简简单单进度条
前端
uup39 分钟前
JavaScript 中 this 指向问题
javascript
倚栏听风雨1 小时前
详解 TypeScript 中,async 和 await
前端