#12
数组操作大全
Champ2025.12.18 16:07created at 2025.12.18 16:07updated at 2025.12.18 16:07
0 次阅读

Js中的数组操作方法大全
一、创建数组
// 字面量创建
const arr1: number[] = [1, 2, 3];
const arr2: Array<string> = ["a", "b", "c"]; // 泛型语法
// 构造函数创建
const arr3: number[] = new Array(1, 2, 3);
const emptyArr: number[] = new Array(3); // 长度为3的空数组
// 使用 Array.from()
const arr4: number[] = Array.from([1, 2, 3]);
const arr5: number[] = Array.from({ length: 5 }, (_, i) => i * 2); // [0, 2, 4, 6, 8]
// 使用 Array.of()
const arr6: number[] = Array.of(1, 2, 3, 4, 5);
二、增删改查基础操作
1. 添加元素
const fruits: string[] = ["apple", "banana"];
// 末尾添加
fruits.push("orange"); // ["apple", "banana", "orange"]
const newLength = fruits.push("grape", "mango"); // 返回新长度
// 开头添加
fruits.unshift("strawberry"); // ["strawberry", "apple", "banana", ...]
// 任意位置添加 (使用 splice)
//array.splice(startIndex(负数表示从后往前,超出长度从末尾开始), deleteCount(超出长度删除所有), item1, item2, ..., itemN) 返回被删除元素组成的数组
fruits.splice(2, 0, "peach"); // 在索引2处插入,不删除元素
// ["strawberry", "apple", "peach", "banana", ...]
2. 删除元素
const numbers: number[] = [1, 2, 3, 4, 5];
// 删除最后一个
const last = numbers.pop(); // last = 5, numbers = [1, 2, 3, 4]
// 删除第一个
const first = numbers.shift(); // first = 1, numbers = [2, 3, 4]
// 删除指定位置 (splice)
const removed = numbers.splice(1, 2); // 从索引1开始删除2个元素
// removed = [3, 4], numbers = [2]
// 删除所有元素
numbers.length = 0; // []
3. 修改元素
const colors: string[] = ["red", "green", "blue"];
// 直接赋值
colors[1] = "yellow"; // ["red", "yellow", "blue"]
// 使用 splice 替换
colors.splice(0, 1, "purple"); // 替换索引0的元素
// ["purple", "yellow", "blue"]
// 使用 fill 填充
const filled = new Array(3).fill(0); // [0, 0, 0]
filled.fill(1, 1, 3); // [0, 1, 1] (从索引1开始到3填充1)
4. 查找元素
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Alice" }
];
// 根据值查找索引
const index = users.findIndex(user => user.name === "Bob"); // 1
// 查找元素
const user = users.find(user => user.id === 2); // { id: 2, name: "Bob" }
// 检查是否存在
const hasAlice = users.some(user => user.name === "Alice"); // true
// 检查是否全部满足
const allHaveId = users.every(user => user.id > 0); // true
// 线性查找
const indexOfAlice = users.indexOf(users.find(u => u.name === "Alice")!); // 0
const lastIndexOfAlice = users.lastIndexOf(users.find(u => u.name === "Alice")!); // 2
三、遍历方法
const numbers: number[] = [1, 2, 3, 4, 5];
// forEach - 单纯遍历
numbers.forEach((num, index) => {
console.log(`Index ${index}: ${num}`);
});
// map - 返回新数组
const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]
// filter - 过滤
const even = numbers.filter(num => num % 2 === 0); // [2, 4]
// reduce - 累加
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 15
const max = numbers.reduce((a, b) => Math.max(a, b)); // 5
// reduceRight - 从右向左累加
const reversedStr = ["a", "b", "c"].reduceRight((acc, curr) => acc + curr); // "cba"
// flatMap - 先map后flat(一层)
const nested = [1, 2, 3].flatMap(x => [x, x * 2]); // [1, 2, 2, 4, 3, 6]
四、数组转换
// slice - 创建子数组(浅拷贝)
const arr = [1, 2, 3, 4, 5];
const slice1 = arr.slice(1, 3); // [2, 3] (索引1到3,不包含3)
const slice2 = arr.slice(-2); // [4, 5] (最后两个)
// concat - 合并数组
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = arr1.concat(arr2, [5, 6]); // [1, 2, 3, 4, 5, 6]
// flat - 扁平化数组
const nestedArr = [1, [2, 3], [4, [5, 6]]];
const flat1 = nestedArr.flat(); // [1, 2, 3, 4, [5, 6]]
const flat2 = nestedArr.flat(2); // [1, 2, 3, 4, 5, 6]
// join - 转为字符串
const str = arr.join(", "); // "1, 2, 3, 4, 5"
// toString / toLocaleString
const dateArr = [new Date(), new Date()];
dateArr.toString(); // "Thu Dec 12 2024..."
dateArr.toLocaleString('zh-CN'); // "2024/12/12..."
五、排序和反转
// sort - 排序(原地修改)
const unsorted = [3, 1, 4, 1, 5];
unsorted.sort(); // [1, 1, 3, 4, 5]
// 自定义排序
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 20 }
];
users.sort((a, b) => a.age - b.age); // 按年龄升序
users.sort((a, b) => b.age - a.age); // 按年龄降序
users.sort((a, b) => a.name.localeCompare(b.name)); // 按名字字母排序
// reverse - 反转(原地修改)
const arr = [1, 2, 3];
arr.reverse(); // [3, 2, 1]
// 创建排序后的新数组(不修改原数组)
const sorted = [...users].sort((a, b) => a.age - b.age);
六、查找和验证
const numbers = [1, 2, 3, 4, 5, NaN];
// includes - 检查包含(ES7)
const hasThree = numbers.includes(3); // true
const hasNaN = numbers.includes(NaN); // true (与 indexOf 不同)
// indexOf / lastIndexOf
const firstIndex = numbers.indexOf(3); // 2
const lastIndex = numbers.lastIndexOf(3); // 2
// find / findIndex / findLast / findLastIndex(ES2023)
const arr = [5, 12, 8, 130, 44];
const found = arr.find(element => element > 10); // 12
const foundIndex = arr.findIndex(element => element > 10); // 1
const foundLast = arr.findLast(element => element > 10); // 44 (ES2023)
const foundLastIndex = arr.findLastIndex(element => element > 10); // 4 (ES2023)
七、类型安全的数组操作(TypeScript特有)
// 1. 类型保护
function processArray(arr: (string | number)[]): string[] {
// 类型守卫
return arr.filter((item): item is string => typeof item === "string");
}
// 2. 只读数组
const readOnlyArr: readonly number[] = [1, 2, 3];
// readOnlyArr.push(4); // 错误:push不存在于类型'readonly number[]'
// 3. 元组类型
const tuple: [string, number] = ["Alice", 25];
tuple[0] = "Bob"; // OK
// tuple[2] = "extra"; // 错误:长度为 "2" 的元组类型 "[string, number]" 在索引 "2" 处没有元素
// 4. 使用泛型
function getFirst<T>(arr: T[]): T | undefined {
return arr[0];
}
const firstNum = getFirst([1, 2, 3]); // number
const firstStr = getFirst(["a", "b"]); // string
// 5. 类型断言
const mixed = ["text", 123, true] as const; // 变成只读字面量类型
八、实用技巧和最佳实践
// 1. 数组去重
const duplicates = [1, 2, 2, 3, 4, 4, 5];
const unique1 = [...new Set(duplicates)]; // [1, 2, 3, 4, 5]
const unique2 = Array.from(new Set(duplicates));
// 对象数组去重
const objects = [{id: 1}, {id: 2}, {id: 1}];
const uniqueObjects = Array.from(
new Map(objects.map(item => [item.id, item])).values()
);
// 2. 数组分组
const groupBy = <T>(arr: T[], keyFn: (item: T) => string): Record<string, T[]> => {
return arr.reduce((groups, item) => {
const key = keyFn(item);
groups[key] = groups[key] || [];
groups[key].push(item);
return groups;
}, {} as Record<string, T[]>);
};
// 3. 分页功能
function paginate<T>(array: T[], pageSize: number, pageNumber: number): T[] {
return array.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
}
// 4. 数组交集、并集、差集
const a = [1, 2, 3];
const b = [2, 3, 4];
const union = [...new Set([...a, ...b])]; // [1, 2, 3, 4]
const intersection = a.filter(x => b.includes(x)); // [2, 3]
const difference = a.filter(x => !b.includes(x)); // [1]
// 5. 安全访问(避免undefined)
const safeGet = <T>(arr: T[], index: number): T | undefined => {
return arr.at(index); // ES2022的at方法,支持负数索引
};
const lastItem = arr.at(-1); // 最后一个元素
const secondLast = arr.at(-2); // 倒数第二个
九、性能考虑
// 1. 大规模数据使用Set提高查找性能
const largeArray = new Array(1000000).fill(0).map((_, i) => i);
const lookupSet = new Set(largeArray); // O(1)查找
// 2. 避免在循环中修改数组长度
// ❌ 不好
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 0) {
arr.splice(i, 1); // 改变长度,需要调整索引
i--; // 需要手动调整
}
}
// ✅ 更好
arr = arr.filter(item => item !== 0);
// 或者从后向前遍历
for (let i = arr.length - 1; i >= 0; i--) {
if (arr[i] === 0) {
arr.splice(i, 1); // 不会影响前面的索引
}
}
// 3. 链式调用优化
const result = largeArray
.filter(x => x % 2 === 0) // 先过滤减少数据量
.map(x => x * 2) // 再转换
.slice(0, 10); // 最后取部分
十、ES2023+ 新特性
// 1. toReversed / toSorted / toSpliced(ES2023)
const original = [3, 1, 2];
const sorted = original.toSorted(); // [1, 2, 3],original不变
const reversed = original.toReversed(); // [2, 1, 3],original不变
const spliced = original.toSpliced(1, 1, 4); // [3, 4, 2],original不变
// 2. with 方法(ES2023)- 不可变更新
const arr = [1, 2, 3];
const newArr = arr.with(1, 99); // [1, 99, 3],arr不变
// 3. findLast / findLastIndex(ES2023)
const lastEven = [1, 2, 3, 4, 5].findLast(x => x % 2 === 0); // 4
const lastEvenIndex = [1, 2, 3, 4, 5].findLastIndex(x => x % 2 === 0); // 3
总结表
| 操作类型 | 方法 | 是否修改原数组 | 返回值 |
|---|---|---|---|
| 添加 | push, unshift, splice | ✅ | 新长度/删除的元素 |
| 删除 | pop, shift, splice | ✅ | 删除的元素 |
| 修改 | fill, splice, 直接赋值 | ✅ | 修改后的数组 |
| 查找 | find, indexOf, includes | ❌ | 元素/索引/布尔值 |
| 遍历 | forEach, map, filter, reduce | ❌ | 根据方法不同 |
| 转换 | slice, concat, flat, join | ❌ | 新数组/字符串 |
| 排序 | sort, reverse | ✅ | 排序后的数组 |
| 验证 | some, every | ❌ | 布尔值 |
最佳实践建议:
- 使用不可变方法(如
map,filter,slice)以避免副作用 - 复杂操作考虑使用
reduce或组合多个方法 - TypeScript 中充分利用类型系统,使用泛型增强复用性
- 大数据集时注意性能,使用
Set优化查找