ES6(ES2015)之后,JavaScript 数组新增了多个实用方法,覆盖迭代、查找、转换、填充、合并等场景,大幅提升了数组操作的简洁性和效率。以下按 ES 版本分类,详解各新增方法的用法、参数、返回值及场景,附带示例代码:
一、ES2015(ES6):数组基础增强
ES6 是数组方法的 “爆发期”,新增方法覆盖迭代、查找、转换等核心场景,奠定了现代数组操作的基础。
1. Array.from():类数组 / 可迭代对象转数组
功能
将类数组对象(有 length 属性 + 索引属性,如 arguments、DOM 集合)或可迭代对象(如 Set、Map、字符串)转换为真正的数组。
语法
Array.from(arrayLike[, mapFn[, thisArg]])
arrayLike:必选,类数组 / 可迭代对象;mapFn:可选,映射函数(类似Array.prototype.map),对每个元素处理后返回;thisArg:可选,mapFn中的this指向。
示例
// 1. 类数组对象(arguments)
function sum() {
return Array.from(arguments).reduce((a, b) => a + b, 0);
}
sum(1, 2, 3); // 6
// 2. DOM 集合(NodeList)
const lis = document.querySelectorAll('li');
const liTexts = Array.from(lis, li => li.textContent); // 直接映射,无需二次遍历
// 3. 可迭代对象(Set)
const set = new Set([1, 2, 2, 3]);
Array.from(set); // [1, 2, 3](去重)
// 4. 字符串(可迭代)
Array.from('abc'); // ['a', 'b', 'c']
优势
相比 Array.prototype.slice.call(arrayLike),支持映射函数,更简洁;支持所有可迭代对象(如 Set),兼容性更广。
2. Array.of():创建指定元素的数组
功能
创建一个包含所有传入参数的数组,解决 new Array() 的歧义问题。
语法
Array.of(element0[, element1[, ...[, elementN]]])
示例(对比 new Array())
// 问题:new Array(n) 若传入单个数字,会创建长度为 n 的空数组
new Array(3); // [empty × 3](空数组,无实际元素)
new Array(1, 2, 3); // [1, 2, 3](正常)
// 解决:Array.of 始终将参数作为元素
Array.of(3); // [3](单个数字作为元素)
Array.of(1, 2, 3); // [1, 2, 3]
Array.of(); // [](无参数返回空数组)
场景
需要明确创建 “包含指定元素” 的数组时(如动态参数场景),优先使用 Array.of。
3. 实例方法:find() / findIndex():查找元素 / 索引
功能
find():查找数组中第一个满足条件的元素,返回该元素(无则返回undefined);findIndex():查找数组中第一个满足条件的元素,返回其索引(无则返回-1)。
语法
arr.find((item, index, array) => condition);
arr.findIndex((item, index, array) => condition);
- 回调函数参数:
item(当前元素)、index(当前索引)、array(原数组); - 找到后立即终止遍历(性能优于
filter+[0])。
示例
const users = [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' },
{ id: 3, name: '王五' }
];
// 查找 id=2 的用户
users.find(user => user.id === 2); // { id: 2, name: '李四' }
// 查找 id=4 的用户(无结果)
users.find(user => user.id === 4); // undefined
// 查找 id=3 的索引
users.findIndex(user => user.id === 3); // 2
// 查找不存在元素的索引
users.findIndex(user => user.id === 4); // -1
场景
- 按条件查找单个元素(如用户详情);
- 按条件查找元素位置(如删除、替换元素)。
4. 实例方法:fill():填充数组
功能
用指定值填充数组的指定范围(覆盖原有元素),返回修改后的原数组( mutable,可变)。
语法
arr.fill(value[, start[, end]])
value:填充值(可以是任意类型,如对象、数组);start:可选,起始索引(默认 0);end:可选,结束索引(默认arr.length,不包含end本身);- 支持负数索引(如
start=-2表示倒数第二个元素)。
示例
// 1. 填充整个数组
const arr1 = [1, 2, 3];
arr1.fill(0); // [0, 0, 0](原数组被修改)
// 2. 填充指定范围(start=1,end=3)
const arr2 = [1, 2, 3, 4];
arr2.fill(9, 1, 3); // [1, 9, 9, 4](索引 1、2 被填充)
// 3. 负数索引(start=-2,从倒数第二个开始)
const arr3 = [1, 2, 3, 4];
arr3.fill(5, -2); // [1, 2, 5, 5]
// 4. 填充引用类型(注意:所有位置共享同一个对象)
const arr4 = new Array(3).fill({ name: '默认' });
arr4[0].name = '修改'; // 所有元素的 name 都变成 '修改'(引用共享)
注意
填充引用类型(如对象、数组)时,所有填充位置会指向同一个引用,修改一个会影响所有,需谨慎使用(如需独立对象,可结合 map:Array(3).fill().map(() => ({ name: '默认' })))。
5. 实例方法:entries() / keys() / values():迭代器方法
功能
返回数组的迭代器对象,支持 for...of 循环遍历,分别获取 “键值对”“索引”“元素值”。
语法与示例
const arr = ['a', 'b', 'c'];
// 1. entries():返回 [索引, 元素] 键值对迭代器
for (const [index, value] of arr.entries()) {
console.log(index, value); // 0 'a' → 1 'b' → 2 'c'
}
Array.from(arr.entries()); // [[0, 'a'], [1, 'b'], [2, 'c']](转数组)
// 2. keys():返回索引迭代器
for (const index of arr.keys()) {
console.log(index); // 0 → 1 → 2
}
// 3. values():返回元素值迭代器
for (const value of arr.values()) {
console.log(value); // 'a' → 'b' → 'c'
}
场景
- 需同时获取索引和元素时,用
entries()(替代for循环的i和arr[i]); - 仅需索引或元素时,用
keys()/values()(语义更清晰)。
二、ES2016(ES7):小幅度补充
ES7 仅新增 1 个数组实例方法,聚焦 “包含判断”。
实例方法:includes():判断元素是否存在
功能
判断数组是否包含指定元素,返回布尔值(替代 indexOf !== -1)。
语法
arr.includes(valueToFind[, fromIndex])
valueToFind:要查找的元素;fromIndex:可选,起始查找索引(默认 0,支持负数);- 支持
NaN查找(indexOf不支持)。
示例
const arr = [1, 2, 3, NaN];
// 基础用法
arr.includes(2); // true
arr.includes(4); // false
// 起始索引(从索引 2 开始查找)
arr.includes(3, 2); // true
arr.includes(2, 2); // false
// 负数索引(从倒数第二个元素开始查找)
arr.includes(3, -2); // true
// 查找 NaN(indexOf 无法做到)
arr.includes(NaN); // true
arr.indexOf(NaN); // -1(失效)
优势
- 语义更清晰(
includes直接表达 “包含”,indexOf表达 “索引”); - 支持
NaN查找(解决indexOf的痛点)。
三、ES2019(ES10):数组扁平化与过滤
ES10 新增 2 个高频方法,解决 “数组扁平化” 和 “空元素过滤” 问题。
1. 实例方法:flat():数组扁平化
功能
将嵌套数组 “拉平” 为一维或指定深度的数组,返回新数组( immutable,不可变)。
语法
arr.flat([depth])
depth:可选,扁平化深度(默认 1,支持Infinity表示无限深度);- 自动过滤数组中的空元素(
empty)。
示例
// 1. 一维嵌套(默认 depth=1)
const arr1 = [1, [2, [3]]];
arr1.flat(); // [1, 2, [3]](仅拉平一层)
// 2. 指定深度(depth=2)
arr1.flat(2); // [1, 2, 3](拉平两层)
// 3. 无限深度(拉平所有嵌套)
const arr2 = [1, [2, [3, [4]]]];
arr2.flat(Infinity); // [1, 2, 3, 4]
// 4. 过滤空元素
const arr3 = [1, , 3, [4, , 6]];
arr3.flat(); // [1, 3, 4, 6](空元素被自动过滤)
场景
处理后端返回的嵌套数据(如树形结构、多级列表),快速转为一维数组。
2. 实例方法:flatMap():映射 + 扁平化
功能
先对数组元素执行 map 映射,再对结果执行 flat(depth=1) 扁平化,返回新数组(相当于 arr.map(...).flat(1),但效率更高)。
语法
arr.flatMap((item, index, array) => mapFnResult)
- 映射函数返回值可以是数组(会被拉平一层)或非数组(直接保留)。
示例
// 1. 映射后扁平化(替代 map + flat(1))
const arr1 = ['hello world', 'ES6+'];
// 先 split 成数组,再拉平一层
arr1.flatMap(str => str.split(' ')); // ['hello', 'world', 'ES6+']
// 等价于(但 flatMap 更高效)
arr1.map(str => str.split(' ')).flat(1);
// 2. 过滤 + 映射(返回空数组则忽略)
const arr2 = [1, 2, 3, 4];
// 偶数乘 2,奇数过滤(返回空数组不保留)
arr2.flatMap(num => num % 2 === 0 ? [num * 2] : []); // [4, 8]
场景
需要 “映射后立即扁平化一层” 的场景(如字符串分割、数据拆分),比 map + flat 更简洁高效。
四、ES2022(ES13):查找与复制增强
ES2022 新增 2 个方法,优化 “反向查找” 和 “数组复制” 体验。
1. 实例方法:findLast() / findLastIndex():反向查找
功能
findLast():从数组末尾开始查找,返回第一个满足条件的元素(无则undefined);findLastIndex():从数组末尾开始查找,返回第一个满足条件的元素索引(无则-1)。
语法
arr.findLast((item, index, array) => condition);
arr.findLastIndex((item, index, array) => condition);
- 找到后立即终止遍历(性能优于
reverse()+find())。
示例
const numbers = [1, 2, 3, 4, 5];
// 查找最后一个偶数
numbers.findLast(num => num % 2 === 0); // 4
// 查找最后一个大于 5 的数(无结果)
numbers.findLast(num => num > 5); // undefined
// 查找最后一个偶数的索引
numbers.findLastIndex(num => num % 2 === 0); // 3
// 查找最后一个大于 5 的数的索引(无结果)
numbers.findLastIndex(num => num > 5); // -1
场景
需要从末尾查找元素的场景(如最近的操作记录、最后一个满足条件的数据)。
2. 实例方法:with():修改指定索引元素(不可变)
功能
修改数组指定索引的元素,返回新数组( immutable,不修改原数组),替代直接赋值(arr[index] = value, mutable)。
语法
arr.with(index, value)
index:要修改的索引(支持负数,如-1表示最后一个元素);value:新值;- 原数组保持不变,返回修改后的新数组。
示例
const arr = [1, 2, 3, 4];
// 修改索引 1 的元素(返回新数组)
const newArr = arr.with(1, 9);
newArr; // [1, 9, 3, 4]
arr; // [1, 2, 3, 4](原数组未变)
// 负数索引(修改最后一个元素)
arr.with(-1, 10); // [1, 2, 3, 10]
// 索引超出范围(返回原数组,无修改)
arr.with(10, 100); // [1, 2, 3, 4]
优势
- 不可变操作,避免修改原数组(适合 React、Vue 等状态管理场景);
- 语法简洁,链式调用更友好(如
arr.with(1,9).map(...))。
五、ES2023(ES14):数组从末尾复制
ES2023 新增 1 个方法,优化 “从数组末尾复制元素” 的场景。
实例方法:toReversed() / toSorted() / toSpliced()(补充:ES2023 核心数组方法)
说明
ES2023 新增 3 个不可变版本的数组方法,对应原有可变方法,返回新数组,不修改原数组:
toReversed():替代reverse()(反转数组);toSorted(compareFn):替代sort()(排序数组);toSpliced(start, deleteCount, ...items):替代splice()(删除 / 插入元素)。
重点:toSpliced()(从末尾复制 / 删除场景)
语法
arr.toSpliced(start, deleteCount, ...items)
start:起始索引(支持负数);deleteCount:要删除的元素个数;...items:要插入的元素(可选);- 返回新数组,原数组不变。
示例
const arr = [1, 2, 3, 4, 5];
// 1. 从末尾删除 2 个元素(start=-2,deleteCount=2)
const newArr1 = arr.toSpliced(-2, 2);
newArr1; // [1, 2, 3](删除最后 2 个元素)
arr; // [1, 2, 3, 4, 5](原数组未变)
// 2. 从索引 2 开始,删除 1 个元素,插入 6、7
const newArr2 = arr.toSpliced(2, 1, 6, 7);
newArr2; // [1, 2, 6, 7, 4, 5]
// 3. 不可变反转(toReversed)
arr.toReversed(); // [5, 4, 3, 2, 1]
arr; // 原数组不变
// 4. 不可变排序(toSorted)
const numArr = [3, 1, 2];
numArr.toSorted((a, b) => a - b); // [1, 2, 3]
numArr; // 原数组不变
场景
需要修改数组但不影响原数组的场景(如状态管理、函数式编程),替代原有可变方法(reverse/sort/splice)。
六、各版本新增方法汇总表
| ES 版本 | 方法类型 | 方法名 | 核心功能 | 特点 / 场景 |
|---|---|---|---|---|
| ES2015 | 静态方法 | Array.from() | 类数组 / 可迭代对象转数组 | 支持映射,替代 slice.call |
| ES2015 | 静态方法 | Array.of() | 创建指定元素的数组 | 解决 new Array() 歧义 |
| ES2015 | 实例方法 | find() | 查找第一个满足条件的元素 | 找到即终止,返回元素 |
| ES2015 | 实例方法 | findIndex() | 查找第一个满足条件的元素索引 | 找到即终止,返回索引 |
| ES2015 | 实例方法 | fill() | 填充数组指定范围 | 可变,支持引用类型(注意共享引用) |
| ES2015 | 实例方法(迭代) | entries()/keys()/values() | 返回迭代器 | 支持 for...of,获取键值对 / 索引 / 元素 |
| ES2016 | 实例方法 | includes() | 判断元素是否存在 | 支持 NaN,语义清晰 |
| ES2019 | 实例方法 | flat() | 数组扁平化 | 不可变,自动过滤空元素 |
| ES2019 | 实例方法 | flatMap() | 映射 + 扁平化(depth=1) | 替代 map + flat(1),高效 |
| ES2022 | 实例方法 | findLast() | 反向查找第一个满足条件的元素 | 从末尾开始,找到即终止 |
| ES2022 | 实例方法 | findLastIndex() | 反向查找第一个满足条件的元素索引 | 从末尾开始,找到即终止 |
| ES2022 | 实例方法 | with() | 修改指定索引元素(不可变) | 不修改原数组,适合状态管理 |
| ES2023 | 实例方法 | toReversed() | 反转数组(不可变) | 替代 reverse(),不修改原数组 |
| ES2023 | 实例方法 | toSorted() | 排序数组(不可变) | 替代 sort(),不修改原数组 |
| ES2023 | 实例方法 | toSpliced() | 删除 / 插入元素(不可变) | 替代 splice(),不修改原数组 |
七、核心使用建议
- 优先使用不可变方法:ES2022+ 新增的
with()、toReversed()、toSorted()、toSpliced()不修改原数组,适合状态管理(React/Vue)和函数式编程; - 替代旧写法:
- 类数组转数组:用
Array.from()替代Array.prototype.slice.call(); - 包含判断:用
includes()替代indexOf !== -1(支持NaN); - 映射 + 扁平化:用
flatMap()替代map().flat(1)(效率更高);
- 类数组转数组:用
- 注意引用类型风险:
fill()填充对象 / 数组时,所有位置共享引用,需用map生成独立实例; - 性能优化:
find()/findLast()找到元素后立即终止遍历,性能优于filter()[0]或reverse().find()。
这些方法大幅简化了数组操作,减少了手动遍历和临时变量,是现代 JavaScript 开发的必备技能。


1172

被折叠的 条评论
为什么被折叠?



