数组的常用方法
- 迭代方法:forEach,map,filter,reduce...
- 修改原数组:push,pop,shift,unshift,splice,sort,reverse...
- 返回新数组:slice,concat,map,filter,reduce...
1.map()
对数组中的每个元素进行处理,并返回一个新数组。
- 遍历数组的每一个元素
- 对每个元素应用一个回调函数
- 返回一个新数组,数组中的每个元素是回调函数的返回值
const newArray = array.map(function callback(currentValue, index, array) { // return element for newArray }[, thisArg])
// `currentValue`:当前处理的元素
//`index`(可选):当前元素的索引
//`array`(可选):原数组
//`thisArg`(可选):执行回调时的 `this` 值
//使用
const numbers = [1, 2, 3];
const list = numbers.map(num => ({ value: num }));
console.log(list); // [ { value: 1 }, { value: 2 }, { value: 3 } ]
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" }
];
const names = users.map(user => user.name);
console.log(names); // ["Alice", "Bob", "Charlie"]
| 注意点 | 说明 |
|---|---|
| 不改变原数组 | map() 返回新数组,原数组保持不变 |
| 顺序保留 | 新数组的顺序与原数组一致 |
| 稀疏数组 | 如果原数组是稀疏的(如 [1, , 3]),map() 会保留空位(但值为 undefined) |
| 回调必须返回值 | 否则新数组元素会是 undefined |
2.forEach()
用于对数组的每个元素执行一次提供的函数(回调函数)。
array.forEach(function(currentValue, index, array) {
// 执行操作
}, thisArg)
| 参数 | 是否必需 | 说明 |
| ------------------------------------ | --- | ------------------ |
| function(currentValue, index, array) | ✅ 是 |对每个元素执行的函数|
| thisArg | ❌ 否|可选,执行回调时用作 this 的值|
//currentValue :当前正在处理的元素(必填)
//index:当前元素的索引(可选)
//array:调用forEach()的数组本身(可选)
//使用
let numbers = [1, 2, 3];
numbers.forEach((num, index, arr) => {
arr[index] = num * 2;
});
console.log(numbers); // [2, 4, 6]
const obj = {
multiplier: 2,
multiply: function(arr) {
arr.forEach(function(num) {
console.log(num * this.multiplier);
}, this);
}
};
obj.multiply([1, 2, 3]);
// 输出:2, 4, 6
| 注意点 | 说明 |
|---|---|
| 不改变原数组 | forEach() 返没有返回值(返回undefined) |
| 会遍历每个元素 | 包括空元素(稀疏数组中 undefined 会被遍历) |
| 无法中途退出 | 没有 break,不能提前终止(想提前终止请用 for 或 for...of) |
| 修改原数组需手动操作 | forEach() 不会自动修改原数组,但可以在回调中修改 |
3.filter()
用于筛选数组中符合条件的元素,并返回一个新数组,包含所有通过条件的元素。
- 遍历数组中的每一个元素
- 对每个元素执行一个回调函数
- 如果回调函数返回
true,该元素保留在新数组中;否则被过滤掉
const newArray = array.filter(function callback(currentValue, index, array) {
// return 条件表达式
}[, thisArg])
//`currentValue`:当前处理的元素
// `index`(可选):当前元素的索引
//`array`(可选):原数组
//`thisArg`(可选):执行回调时的 `this` 值
//使用
const users = [
{ id: 1, name: "Alice", age: 25 },
{ id: 2, name: "Bob", age: 17 },
{ id: 3, name: "Charlie", age: 30 }
];
const adults = users.filter(user => user.age >= 18);
console.log(adults);
// [
// { id: 1, name: "Alice", age: 25 },
// { id: 3, name: "Charlie", age: 30 }
// ]
const numbers = [1, 2, 3, 4, 5, 6];
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4, 6]
| 注意点 | 说明 |
|---|---|
| 不改变原数组 | filter() 返回新数组,原数组保持不变 |
| 返回值类型 | 总是返回数组,即使没有符合条件的元素 |
| 回调函数必须返回布尔值 | 否则将自动转换为布尔值(如 0, null, undefined 会被视为 false) |
| 稀疏数组 | 如果原数组是稀疏的(如 [1, , 3]),filter() 会跳过空位 |
4.reduce()
用于将数组中的元素逐个处理,并最终归并为一个单一的值。它是函数式编程中非常强大、灵活的工具,常用于求和、计数、分组、扁平化等场景。
- 遍历数组的每个元素
- 对每个元素执行一个**“归并函数”(reducer)**
- 将上一次的结果作为输入,继续处理下一个元素
- 最终返回一个累积后的结果值
array.reduce(function(accumulator, currentValue, index, array) {
// 返回新的 accumulator 值
}, initialValue)
参数 | 含义 |
| ------------------ | -------------------------- |
| `accumulator` | 累积器,保存“累计”的结果 |
| `currentValue` | 当前正在处理的元素 |
| `index`(可选) | 当前元素的索引 |
| `array`(可选) | 原数组 |
| `initialValue`(可选) | 初始值(可选),如果没有提供,则第一个元素作为初始值
使用
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 10 求和
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, num) => acc + num);
console.log(sum); // 10 没有初始值
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const count = fruits.reduce((acc, fruit) => { acc[fruit] = (acc[fruit] || 0) + 1;
return acc; }, {});
console.log(count);
// 输出: 统计数组中元素出现次数
// { apple: 3, banana: 2, orange: 1 }
| 注意点 | 说明 |
|---|---|
reduce() 不会改变原数组 | 返回一个新值 |
initialValue 是可选的 | 如果不提供,默认第一个元素作为初始值 |
| 如果数组为空且没有初始值 | 会抛出错误 |
reduce() 可以返回任意类型 | 数字、字符串、对象、数组等都可以 |
5.concat()
用于合并两个或多个数组,并返回一个新的数组,不会修改原数组。
array.concat(value1, value2, ..., valueN)
//value1, value2, ...:可以是数组、元素值,或类数组对象。
//返回一个新的数组,是原数组与所有参数连接后的结果。
//使用
const arr1 = [1, 2];
const arr2 = [3, 4];
const newArr = arr1.concat(arr2);
console.log(newArr); // [1, 2, 3, 4]
const arr = [1, 2];
const newArr = arr.concat(3, [4, 5], 'hello');
console.log(newArr); // [1, 2, 3, 4, 5, "hello"]
const arr = [1, 2];
const result = arr.concat([3, [4, 5]]);
console.log(result); // [1, 2, 3, [4, 5]] —— 注意 4 和 5 没有展开
//注意:JavaScript 的字符串也有 concat() 方法,用于拼接字符串:
const str = 'Hello'.concat(', ', 'world', '!');
console.log(str); // "Hello, world!"
| 注意点 | 说明 |
|---|---|
| 不会修改原数组 | concat() 返回新数组,原数组不变 |
| 扁平化处理 | 如果参数是数组,则会将数组中的元素逐个加入新数组(不会合并嵌套多层) |
| 支持多种参数类型 | 可以传入数组,基本类型,对象等 |
6.slice()
用于从原始数组或字符串中提取一部分内容并返回一个新数组或新字符串,不会修改原数组或原字符串。
array.slice(start, end)
//`start`(可选):开始索引(包含),默认为 0。
//`end`(可选):结束索引(不包含),默认为数组长度。
//如果只传一个参数,那它就是 start,end 默认是 array.length
//使用
const arr = [1, 2, 3, 4, 5];
console.log(arr.slice(1, 3)); // [2, 3]
console.log(arr.slice(2)); // [3, 4, 5]
console.log(arr.slice()); // [1, 2, 3, 4, 5](浅拷贝)
console.log(arr.slice(-2)); // [4, 5](负数表示从末尾倒数)
| 注意点 | 说明 |
|---|---|
| 不会改变原数组 | slice() 是纯函数,不会改变原数组或者原字符串 |
| 支持负数索引 | 支持负数索引(从末尾倒数),如 -1 表示最后一个元素 |
| 索引越界安全 | 如果start或end超出范围,不会报错,会自动处理为有效范围 |
7.splice()
用于修改数组内容,可以删除元素、添加元素,甚至同时进行删除和添加。
array.splice(start, deleteCount, item1, item2, ...)
参数 | 说明 |
| ------------------- | ----------------- |
| `start` | 开始修改的索引位置(从 0 开始) |
| `deleteCount` | 要删除的元素个数(可为 0) |
| `item1, item2, ...` | 可选,要添加进数组的元素 |
| 返回值 | 一个由被删除元素组成的新数组
//使用
const arr = ['a', 'b', 'c', 'd'];
const removed = arr.splice(1, 2); // 从索引 1 开始,删除 2 个元素
console.log(arr); // ['a', 'd']
console.log(removed); // ['b', 'c']
const arr = ['apple', 'banana', 'orange'];
arr.splice(1, 0, 'grape'); // 在索引 1 前插入 'grape',不删除
console.log(arr); // ['apple', 'grape', 'banana', 'orange']
const arr = ['red', 'green', 'blue'];
arr.splice(1, 1, 'yellow'); // 删除索引 1 的元素,插入 'yellow'
console.log(arr); // ['red', 'yellow', 'blue']
const arr = [1, 2, 3, 4, 5];
arr.splice(1, 2, 'a', 'b', 'c'); // 删除索引 1 开始的 2 个元素,并添加三个新元素
console.log(arr); // [1, 'a', 'b', 'c', 4, 5]
| 注意点 | 说明 |
|---|---|
| 会改变原数组 | splice() 是少数会修改原数组的方法之一 |
| 负数索引 | 支持负数索引(从末尾倒数),如 -1 表示最后一个元素 |
| deleteCount 为 0 | 表示不删除,只添加 |
| 不传 deleteCount | 默认删除从 start 到数组末尾的所有元素 |
| 返回值 | 被删除元素的数组,如果没有删除,返回空数组 [] |
8.push()
用于向数组的末尾添加一个或多个元素,并返回新的数组长度。
array.push(element1, element2, ..., elementN)
//element1, element2, ...:要添加到数组末尾的一个或多个元素。
//返回值:添加元素后数组的新长度。
//会修改原数组(这是它和 slice()、concat() 等方法的重要区别)
//使用
let arr = [1, 2, 3];
let newLength = arr.push(4);
console.log(arr); // [1, 2, 3, 4]
console.log(newLength); // 4
arr.push(5, 6);
console.log(arr); // [1, 2, 3, 4, 5, 6]
let arr = [1, 2];
arr.push('hello', { name: 'Tom' }, () => {});
console.log(arr);
// [1, 2, "hello", { name: 'Tom' }, () => {}]
| 注意点 | 说明 |
|---|---|
| 修改原数组 | push() 会直接修改原数组 |
| 可添加多个元素 | 一次可以添加多个参数,都会被添加到数组末尾 |
| 返回值是新长度 | 返回值是数组的新长度(可用于链式调用或判断) |
| 支持任何类型 | 可以添加数字、字符串、对象、函数等任意类型 |
9.pop()
用于删除数组的最后一个元素,并返回该元素。
array.pop()
//没有参数
//返回值:被删除的最后一个元素
//会修改原数组
//使用
let arr2 = ['apple', 'banana', 'orange'];
console.log(arr2.pop()); // 'orange'
console.log(arr2); // ['apple', 'banana']
| 注意点 | 说明 |
|---|---|
| 修改原数组 | pop()会直接从数组中删除最后一个元素 |
| 没有参数 | 不需要传参 |
| 返回值是被删除的元素 | 可以用于链式调用或赋值 |
| 若数组为空 | 返回undefined |
10.unshift()
用于向数组的开头(最前面)添加一个或多个元素,并返回新的数组长度。
array.unshift(element1, element2, ..., elementN)
//element1, element2, ...:要添加到数组开头的一个或多个元素。
//返回值:添加元素后数组的新长度。
//会修改原数组(与 push() 类似,但添加位置不同)
//使用
let arr = [2, 3, 4];
let newLength = arr.unshift(1);
console.log(arr); // [1, 2, 3, 4]
console.log(newLength); // 4
arr.unshift(-1, 0);
console.log(arr); // [-1, 0, 1, 2, 3, 4]
| 注意点 | 说明 |
|---|---|
| 修改原数组 | unshift()会直接修改原数组 |
| 可以添加多个元素 | 一次可以添加多个参数,都会被添加到数组的开头 |
| 返回值是新长度 | 返回式是数组的新长度(可用于链式调用或判断) |
| 支持任何类型 | 可以添加数字、字符串、对象、函数等任意类型 |
11.shift()
用于删除数组的第一个元素,并返回该元素。
array.shift()
//没有参数
//返回值:被删除的数组第一个元素
//会修改原数组
//使用
let arr = [1, 2, 3];
let firstElement = arr.shift();
console.log(arr); // [2, 3]
console.log(firstElement); // 1
| 注意点 | 说明 |
|---|---|
| 修改原数组 | shift()会直接从数组中删除第一个元素 |
| 没有参数 | 不需要传参数 |
| 返回值是被删除的元素 | 可用于链式调用或赋值 |
| 若数组为空 | 返回undefined |
12.sort()
用于对数组元素进行排序的数组方法。
array.sort([compareFunction])
//compareFunction(可选):一个用于比较元素的函数。
//会修改原数组(与 slice()、concat() 不同)
//默认按字符串 Unicode 编码排序(可能会导致数字排序错误)
//使用
//如果不传比较函数,sort() 会将元素转换为字符串,然后按 Unicode 字符顺序排序:
let arr = [10, 5, 2, 20];
arr.sort();
console.log(arr); // [10, 2, 20, 5] ❌ 不符合数字大小排序逻辑
//这是因为在默认排序中,JavaScript 把数字转成字符串后比较,例如:
//"10" < "2" → 因为 '1' < '2'
array.sort((a, b) => {
if (a < b) return -1; // a 排在 b 前面
if (a > b) return 1; // b 排在 a 前面
return 0; // 保持原顺序
});
//可以简写成
array.sort((a, b) => a - b); // 升序
array.sort((a, b) => b - a); // 降序
let users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 20 },
{ name: 'Charlie', age: 30 }
];
// 按年龄升序排序
users.sort((a, b) => a.age - b.age);
console.log(users);
/*
[
{ name: 'Bob', age: 20 },
{ name: 'Alice', age: 25 },
{ name: 'Charlie', age: 30 }
]
*/
| 注意点 | 说明 |
|---|---|
| 修改原数组 | sort()会直接修改原数组 |
| 默认按字符串排序 | 可能不符合数字预期 |
| 支持自定义排序逻辑 | 通过传入比较函数实现 |
| 稳定排序 | ES2019起,sort()是稳定排序(相同值保持原顺序) |
13.reverse()
用于反转数组元素的顺序。
array.reverse()
//没有参数
//会修改原数组
//返回值是修改后的数组本身
//使用
let arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr); // [5, 4, 3, 2, 1]
let arr = [1, 2, 3];
let result = arr.reverse();
console.log(arr); // [3, 2, 1]
console.log(result); // [3, 2, 1](和 arr 是同一个引用)
| 注意点 | 说明 |
|---|---|
| 修改原数组 | reverse()会直接反转原数组 |
| 没有参数 | 不需要传任何参数 |
| 返回数组本身 | 返回的是数组引用,不是新数组 |
| 不影响数组元素本身 | 只是改变元素的顺序,不修改元素内容 |
14.判断数组的方法
var arr = [1,2,3];
console.log(Array.isArray(arr)); //true
console.log(arr instanceof Array); //true
console.log(Object.prototype.toString.call(arr)) //[object Array]
console.log(Object.prototype.toString.call(arr).indexof('Array') != -1) //true 或者>-1
console.log(Array.prototype.isPrototypeOf(arr)) //true
console.log(arr.constructor.toString()) //function Array() {[native code]}
console.log(arr.constructor.toString().indexof('Array') != -1) //true
15.数组去重的方法
1.new Set()
var arr = [1,2,3,4,5,6,6,7,7]
function unique(arr){
return [...new Set(arr)]
}
console.log(unique(arr)) //[1,2,3,4,5,6,7]
2.indexOf
var arr = [1,2,3,4,5,6,6,7,7]
function unique(arr){
var brr = [];
for(var i=0;i<arr.length;i++){
if(brr.indexOf(arr[i]) == -1){
brr.push(arr[i])
}
}
return brr;
}
console.log(unique(arr)) //[1,2,3,4,5,6,7]
3.sort()
var arr = [1,2,3,4,5,6,6,7,7]
function unique(arr){
arr = arr.sort();
var brr = [];
for(var i=0;i<arr.length;i++){
if(arr[i] !== arr[i-1]){
brr.push(arr[i])
}
}
return brr;
}
console.log(unique(arr)) //[1,2,3,4,5,6,7]
4.filter
var arr = [1,2,3,4,5,6,6,7,7]
var arr1 = arr.filter((item, index) => arr.indexOf(item) === index);
console.log(arr1) //[1,2,3,4,5,6,7]
注意
map跟forEach的区别:
- 返回值不同,map返回一个新数组,forEach返回一个undefined
- 用途不同,map用于数据转换,forEach用于执行无返回值的操作
- map可以链式调用,
arr.map(...).filter(...),forEach不行