告别 for 循环!ES6 + 数组新增方法让代码简洁 10 倍

ES6(ES2015)之后,JavaScript 数组新增了多个实用方法,覆盖迭代、查找、转换、填充、合并等场景,大幅提升了数组操作的简洁性和效率。以下按 ES 版本分类,详解各新增方法的用法、参数、返回值及场景,附带示例代码:

一、ES2015(ES6):数组基础增强

ES6 是数组方法的 “爆发期”,新增方法覆盖迭代、查找、转换等核心场景,奠定了现代数组操作的基础。

1. Array.from():类数组 / 可迭代对象转数组

功能

类数组对象(有 length 属性 + 索引属性,如 arguments、DOM 集合)或可迭代对象(如 SetMap、字符串)转换为真正的数组。

语法
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 都变成 '修改'(引用共享)
注意

填充引用类型(如对象、数组)时,所有填充位置会指向同一个引用,修改一个会影响所有,需谨慎使用(如需独立对象,可结合 mapArray(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(),不修改原数组

七、核心使用建议

  1. 优先使用不可变方法:ES2022+ 新增的 with()toReversed()toSorted()toSpliced() 不修改原数组,适合状态管理(React/Vue)和函数式编程;
  2. 替代旧写法
    • 类数组转数组:用 Array.from() 替代 Array.prototype.slice.call()
    • 包含判断:用 includes() 替代 indexOf !== -1(支持 NaN);
    • 映射 + 扁平化:用 flatMap() 替代 map().flat(1)(效率更高);
  3. 注意引用类型风险fill() 填充对象 / 数组时,所有位置共享引用,需用 map 生成独立实例;
  4. 性能优化find()/findLast() 找到元素后立即终止遍历,性能优于 filter()[0] 或 reverse().find()

这些方法大幅简化了数组操作,减少了手动遍历和临时变量,是现代 JavaScript 开发的必备技能。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canjun_wen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值