常用数组方法
常用数组方法
概述
JavaScript 数组提供了丰富的方法来处理数据。本文详细介绍常用数组方法的用法及引入版本。
ES 版本对照表
| 版本 | 年份 | 主要数组新方法 |
|---|---|---|
| ES5 | 2009 | forEach, map, filter, reduce, every, some, indexOf, lastIndexOf, concat, slice, splice, push, pop, shift, unshift, sort, reverse, join, toString |
| ES6 (ES2015) | 2015 | find, findIndex, fill, copyWithin, includes, Array.from, Array.of |
| ES2016 | 2016 | Array.prototype.includes |
| ES2017 | 2017 | flat, flatMap |
| ES2019 | 2019 | flat (增强), Array.prototype.flat |
| ES2021 | 2021 | Array.prototype.at, Promise.allSettled |
| ES2023 | 2023 | toReversed, toSorted, toSpliced, with |
数组创建
Array.of() — ES2016
创建具有可变数量参数的数组。
const arr = Array.of(1, 2, 3, 4, 5);
// [1, 2, 3, 4, 5]
const empty = Array.of();
// []Array.from() — ES2016
从类数组或可迭代对象创建数组。
const str = Array.from("hello");
// ['h', 'e', 'l', 'l', 'o']
const nums = Array.from([1, 2, 3], (x) => x * 2);
// [2, 4, 6]
const set = new Set([1, 2, 3]);
const arr = Array.from(set);
// [1, 2, 3]遍历数组
forEach() — ES5
遍历数组,为每个元素执行回调函数。返回 undefined。
const nums = [1, 2, 3, 4, 5];
nums.forEach((item, index, array) => {
console.log(`索引 ${index}: ${item}`);
});
// 输出: 索引 0: 1, 索引 1: 2, ...find() — ES2016
返回第一个满足条件的元素,没有则返回 undefined。
const users = [
{ id: 1, name: "张三", age: 25 },
{ id: 2, name: "李四", age: 30 },
{ id: 3, name: "王五", age: 28 },
];
const user = users.find((u) => u.age > 26);
// { id: 2, name: '李四', age: 30 }findIndex() — ES2016
返回第一个满足条件的元素的索引,没有则返回 -1。
const nums = [10, 20, 30, 40, 50];
const index = nums.findIndex((n) => n > 25);
// 2 (对应元素 30)findLast() — ES2022
返回最后一个满足条件的元素。
const nums = [5, 12, 8, 130, 44];
const last = nums.findLast((n) => n > 10);
// 44findLastIndex() — ES2022
返回最后一个满足条件的元素的索引。
const nums = [5, 12, 8, 130, 44];
const index = nums.findLastIndex((n) => n > 10);
// 4at() — ES2022
返回指定索引的元素,支持负索引。
const fruits = ["apple", "banana", "orange", "grape"];
fruits.at(0); // 'apple' (正数索引)
fruits.at(-1); // 'grape' (最后一个)
fruits.at(-2); // 'orange'转换数组
map() — ES5
创建一个新数组,结果为回调函数的返回值。
const nums = [1, 2, 3, 4, 5];
const doubled = nums.map((n) => n * 2);
// [2, 4, 6, 8, 10]
const objects = nums.map((n, i) => ({ value: n, index: i }));
// [{value: 1, index: 0}, {value: 2, index: 1}, ...]flatMap() — ES2019
先执行 map,再展开结果(深度为 1)。
const sentences = ["hello world", "foo bar"];
const words = sentences.flatMap((s) => s.split(" "));
// ['hello', 'world', 'foo', 'bar']
const nums = [1, 2, 3];
const result = nums.flatMap((x) => [x, x * 2]);
// [1, 2, 2, 4, 3, 6]flat() — ES2019
将嵌套数组展开为指定深度的新数组。
const nested = [1, [2, [3, [4]]]];
nested.flat(); // [1, 2, [3, [4]]] (默认深度 1)
nested.flat(2); // [1, 2, 3, [4]] (深度 2)
nested.flat(Infinity); // [1, 2, 3, 4] (完全展开)
// 常见用法:去除数组中的空值
const arr = [1, 2, null, 3, undefined, 4];
arr.flatMap((item) => item ?? []);
// [1, 2, 3, 4]筛选数组
filter() — ES5
返回一个新数组,包含所有满足条件的元素。
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evens = nums.filter((n) => n % 2 === 0);
// [2, 4, 6, 8, 10]
const users = [
{ name: "张三", age: 25 },
{ name: "李四", age: 17 },
{ name: "王五", age: 30 },
];
const adults = users.filter((u) => u.age >= 18);
// [{ name: '张三', age: 25 }, { name: '王五', age: 30 }]聚合数组
reduce() — ES5
将数组元素聚合成单个值。
const nums = [1, 2, 3, 4, 5];
// 求和
const sum = nums.reduce((acc, cur) => acc + cur, 0);
// 15
// 求最大值
const max = nums.reduce((a, b) => (a > b ? a : b));
// 5
// 数组去重
const duplicates = [1, 2, 2, 3, 3, 3, 4];
const unique = duplicates.reduce((acc, cur) => {
if (!acc.includes(cur)) acc.push(cur);
return acc;
}, []);
// [1, 2, 3, 4]
// 分组
const people = [
{ name: "张三", group: "A" },
{ name: "李四", group: "B" },
{ name: "王五", group: "A" },
];
const grouped = people.reduce((acc, person) => {
const key = person.group;
if (!acc[key]) acc[key] = [];
acc[key].push(person);
return acc;
}, {});
// { A: [...], B: [...] }reduceRight() — ES5
从右到左遍历的 reduce。
const nested = [
[1, 2],
[3, 4],
[5, 6],
];
const flat = nested.reduceRight((acc, cur) => acc.concat(cur), []);
// [5, 6, 3, 4, 1, 2]判断数组
every() — ES5
检查所有元素是否满足条件,返回布尔值。
const nums = [10, 20, 30, 40];
const allPositive = nums.every((n) => n > 0);
// true
const allGreaterThan25 = nums.every((n) => n > 25);
// falsesome() — ES5
检查是否存在满足条件的元素,返回布尔值。
const nums = [10, 20, 30, 40];
const hasGreaterThan25 = nums.some((n) => n > 25);
// true
const hasNegative = nums.some((n) => n < 0);
// falseincludes() — ES2016
检查数组是否包含指定值,返回布尔值。
const fruits = ["apple", "banana", "orange"];
fruits.includes("banana"); // true
fruits.includes("grape"); // false
fruits.includes("Apple"); // false (区分大小写)查找元素
indexOf() — ES5
返回指定元素的第一个索引,没有则返回 -1。
const fruits = ["apple", "banana", "orange", "banana"];
fruits.indexOf("banana"); // 1
fruits.indexOf("grape"); // -1lastIndexOf() — ES5
返回指定元素的最后一个索引,没有则返回 -1。
const fruits = ["apple", "banana", "orange", "banana"];
fruits.lastIndexOf("banana"); // 3find() / findIndex() — ES2016
见上文「遍历数组」部分。
增删改数组(会修改原数组)
push() — ES5
在数组末尾添加元素,返回新长度。
const arr = [1, 2, 3];
arr.push(4, 5);
// arr: [1, 2, 3, 4, 5], 返回 5pop() — ES5
删除并返回最后一个元素。
const arr = [1, 2, 3, 4, 5];
const popped = arr.pop();
// popped: 5, arr: [1, 2, 3, 4]shift() — ES5
删除并返回第一个元素。
const arr = [1, 2, 3, 4, 5];
const shifted = arr.shift();
// shifted: 1, arr: [2, 3, 4, 5]unshift() — ES5
在数组开头添加元素,返回新长度。
const arr = [3, 4, 5];
arr.unshift(1, 2);
// arr: [1, 2, 3, 4, 5], 返回 5splice() — ES5
删除/替换/添加元素,返回被删除的元素数组。
const arr = [1, 2, 3, 4, 5];
// 删除
arr.splice(1, 2); // [2, 3], arr: [1, 4, 5]
// 替换
const arr2 = [1, 2, 3, 4, 5];
arr2.splice(1, 2, "a", "b"); // [2, 3], arr2: [1, 'a', 'b', 4, 5]
// 插入
const arr3 = [1, 2, 3];
arr3.splice(1, 0, "x", "y"); // [], arr3: [1, 'x', 'y', 2, 3]fill() — ES2016
用指定值填充数组(可指定起始和结束位置)。
const arr = new Array(5);
arr.fill(0); // [0, 0, 0, 0, 0]
const arr2 = [1, 2, 3, 4, 5];
arr2.fill("a", 1, 3); // [1, 'a', 'a', 4, 5]copyWithin() — ES2016
在数组内部复制元素到指定位置。
const arr = [1, 2, 3, 4, 5];
arr.copyWithin(0, 3, 5); // [4, 5, 3, 4, 5]
// 从索引3-5的元素复制到索引0开始的位置toSpliced() — ES2023
返回新数组(原数组不变),执行 splice 操作。
const arr = [1, 2, 3, 4, 5];
const newArr = arr.toSpliced(1, 2, "a", "b");
// newArr: [1, 'a', 'b', 4, 5]
// arr: [1, 2, 3, 4, 5] (不变)排序数组
sort() — ES5
对数组进行原地排序(修改原数组)。
const nums = [3, 1, 5, 2, 4];
// 默认升序(按字符串比较)
nums.sort(); // [1, 2, 3, 4, 5]
// 自定义排序
const nums2 = [3, 1, 5, 2, 4];
nums2.sort((a, b) => a - b); // [1, 2, 3, 4, 5] (升序)
nums2.sort((a, b) => b - a); // [5, 4, 3, 2, 1] (降序)
// 字符串排序
const fruits = ["banana", "apple", "orange", "grape"];
fruits.sort(); // ['apple', 'banana', 'grape', 'orange']
// 中文排序
const names = ["张三", "李四", "王五"];
names.sort((a, b) => a.localeCompare(b, "zh-CN"));reverse() — ES5
反转数组顺序(修改原数组)。
const arr = [1, 2, 3, 4, 5];
arr.reverse();
// [5, 4, 3, 2, 1]toReversed() — ES2023
返回新数组(原数组不变),执行 reverse 操作。
const arr = [1, 2, 3, 4, 5];
const newArr = arr.toReversed();
// newArr: [5, 4, 3, 2, 1]
// arr: [1, 2, 3, 4, 5] (不变)toSorted() — ES2023
返回新数组(原数组不变),执行 sort 操作。
const arr = [3, 1, 5, 2, 4];
const newArr = arr.toSorted((a, b) => a - b);
// newArr: [1, 2, 3, 4, 5]
// arr: [3, 1, 5, 2, 4] (不变)toSorted() — ES2023
返回新数组(原数组不变),执行 sort 操作。
const arr = [3, 1, 5, 2, 4];
const newArr = arr.toSorted((a, b) => a - b);
// newArr: [1, 2, 3, 4, 5]
// arr: [3, 1, 5, 2, 4] (不变)访问/截取数组
concat() — ES5
合并数组,返回新数组。
const arr1 = [1, 2, 3];
const arr2 = [4, 5];
const arr3 = [6, 7, 8];
const merged = arr1.concat(arr2, arr3);
// [1, 2, 3, 4, 5, 6, 7, 8]
// 也可以添加单个值
const result = arr1.concat(4, [5, 6]);
// [1, 2, 3, 4, 5, 6]slice() — ES5
截取数组的一部分,返回新数组。
const arr = [1, 2, 3, 4, 5];
arr.slice(); // [1, 2, 3, 4, 5] (全部)
arr.slice(1); // [2, 3, 4, 5] (从索引1到结尾)
arr.slice(1, 3); // [2, 3] (索引1到3,不包含3)
arr.slice(-2); // [4, 5] (最后2个)
arr.slice(-3, -1); // [3, 4] (倒数第3到倒数第1)join() — ES5
将数组元素连接成字符串。
const arr = ["hello", "world", "!"];
arr.join(); // 'hello,world,!'
arr.join(""); // 'helloworld!'
arr.join("-"); // 'hello-world-!'
// 常用技巧
const chars = ["a", "b", "c"];
chars.join(""); // 'abc'迭代器方法
keys() — ES6
返回数组键的迭代器。
const arr = ["a", "b", "c"];
[...arr.keys()]; // [0, 1, 2]values() — ES6
返回数组值的迭代器。
const arr = ["a", "b", "c"];
[...arr.values()]; // ['a', 'b', 'c']entries() — ES6
返回数组键值对的迭代器。
const arr = ["a", "b", "c"];
for (const [index, value] of arr.entries()) {
console.log(`${index}: ${value}`);
}
// 0: a
// 1: b
// 2: c其他方法
toString() — ES5
将数组转换为字符串。
const arr = [1, 2, 3];
arr.toString(); // '1,2,3'Array.isArray() — ES5
判断是否为数组。
Array.isArray([]); // true
Array.isArray({}); // false
Array.isArray("hello"); // false
Array.isArray(123); // falsewith() — ES2023
返回新数组,替换指定索引的值(原数组不变)。
const arr = [1, 2, 3, 4, 5];
const newArr = arr.with(2, "new");
// newArr: [1, 2, 'new', 4, 5]
// arr: [1, 2, 3, 4, 5] (不变)静态方法
Array.from() / Array.of() — ES2016
见上文「数组创建」部分。
Array.fromAsync() — ES2024
异步版本的 Array.from()。
const asyncIterable = async function* () {
yield 1;
yield 2;
yield 3;
};
const arr = await Array.fromAsync(asyncIterable());
// [1, 2, 3]不可变数组方法总结 (ES2023)
ES2023 引入了多个返回新数组的「不可变」方法,避免修改原数组:
| 方法 | ES版本 | 说明 |
|---|---|---|
| toReversed() | ES2023 | 反转数组,返回新数组 |
| toSorted() | ES2023 | 排序数组,返回新数组 |
| toSpliced() | ES2023 | 增删改数组,返回新数组 |
| with() | ES2023 | 替换指定索引元素,返回新数组 |
// ES2023 不可变方法示例
const original = [1, 2, 3, 4, 5];
original.toReversed(); // [5, 4, 3, 2, 1]
original.toSorted((a, b) => b - a); // [5, 4, 3, 2, 1]
original.toSpliced(1, 2, "a"); // [1, 'a', 4, 5]
original.with(0, "first"); // ['first', 2, 3, 4, 5]
// original 始终不变: [1, 2, 3, 4, 5]方法选择指南
| 场景 | 推荐方法 |
|---|---|
| 遍历元素 | forEach |
| 转换元素 | map |
| 筛选元素 | filter |
| 聚合计算 | reduce |
| 查找元素 | find / findIndex / includes |
| 判断条件 | every / some |
| 排序数组 | sort / toSorted (ES2023) |
| 反转数组 | reverse / toReversed (ES2023) |
| 添加/删除 | push / pop / shift / unshift / splice / toSpliced (ES2023) |
| 合并数组 | concat |
| 截取数组 | slice |
| 展开嵌套 | flat / flatMap |
| 访问元素 | at (ES2022) |