前言
在 JavaScript 开发中,数组操作是频率最高的情景之一。能否熟练掌握数组 API,并分清哪些会改变原数组(Mutator) ,哪些是纯函数(Accessor) ,是判断一个前端基本功是否扎实的重要标准。
一、 检测数组的两种方式
在判断一个变量是否为数组时,typeof 会返回 object,因此我们需要更精准的方法:
instanceof运算符:value instanceof ArrayArray.isArray():Array.isArray(value)(推荐,能跨 iframe 使用)
二、 改变原数组的方法 (Mutator Methods)
这类方法会直接修改调用它的数组。
1. 基础增删:push, pop, shift, unshift
push()/pop():在末尾添加/删除,返回长度/删除值。shift()/unshift():在开头删除/添加,返回删除值/新长度。
2. 万能方法:splice()
splice 是数组中最强大的方法,可以实现删除、插入和替换。
语法:
arr.splice(start, deleteCount, ...items)
- 删除:
arr.splice(1, 2)(从索引 1 开始删除 2 个元素)。 - 替换:
arr.splice(1, 1, 'new')(删除索引 1 的元素并插入新值)。 - 插入:
arr.splice(1, 0, 'add')(在索引 1 前插入元素)。
3. 排序与反转:sort() & reverse()
-
reverse():颠倒数组顺序。 -
sort(fn):默认按字符编码排序。- 数字升序:
arr.sort((a, b) => a - b) - 对象排序:按年龄排序
arr.sort((a, b) => a.age - b.age)
- 数字升序:
4. 填充与内部复制:fill() & copyWithin()
fill(val, start, end):用固定值填充数组。copyWithin(target, start, end):将数组的一部分复制到同一数组中的另一个位置。
三、 不改变原数组的方法 (Accessor Methods)
这类方法会返回一个新数组或结果,原数组保持不变。
1. 迭代器对象:keys(), values(), entries()
ES6 引入,返回迭代器对象,常配合 Array.from() 使用。
keys():返回数组的索引,返回值为一个数组迭代器对象不是直接的数组,需要使用Array.from才能转换成数组values():返回数组里面值,返回值为一个数组迭代器对象不是直接的数组,需要使用Array.from才能转换成数组arr.entries():返回一个索引和原始值键值对,返回值为一个数组迭代器对象不是直接的数组,需要使用Array.from才能转换成数组
const arr = ['a', 'b'];
console.log(Array.from(arr.entries())); // [[0, 'a'], [1, 'b']]
2. 合并与切片:concat() & slice()
-
concat():合并两个或多个数组。 -
slice(start, end):浅拷贝数组的一部分(不包含 end)。- 注意:
splice改变原数组,slice不改变。
- 注意:
3. 查找相关:indexOf, lastIndexOf, includes
indexOf(num): 查找num在数组中的下标lastIndexOf(num):反向查找num在数组中的下标includes():返回布尔值,比indexOf更语义化,且能识别NaN。
4. 数组转换为字符串:join() & toString()
join('-'):将数组元素连接成字符串,可指定分隔符。toString():将数组转换为字符串
四、 面试模拟题(挑战一下)
Q1:如何快速清空一个数组?
参考回答:
arr.length = 0;(最快,且能影响到其他引用)。arr.splice(0, arr.length);(改变原数组)。arr = [];(直接赋值新引用,原引用数组若被其他变量持有则不会被清空)。
Q2:slice() 和 splice() 的核心区别是什么?
参考回答:
- 返回值:两者都返回被截取/删除的子数组。
- 原数组:
slice是纯函数,不改动原数组;splice会直接修改原数组。 - 参数:
slice接收起始和结束索引;splice接收起始索引、删除个数及插入元素。
Q3:sort() 方法在不传参数时有什么隐患?
参考回答:
sort() 默认会将元素转换为字符串再按照 UTF-16 代码单元值序列进行排序。
例如:[1, 10, 2].sort() 的结果是 [1, 10, 2],因为 "10" 的字符编码在 "2" 之前。因此处理数字排序必须传入比较函数。
五、 总结图表
| 方法分类 | 常用 API |
|---|---|
| 会改变原数组 | push, pop, shift, unshift, splice, sort, reverse, fill, copyWithin |
| 不会改变原数组 | slice, concat, join, toString, indexOf, includes, keys, values |