1. 遍历方法
1.1 forEach
-
作用:遍历数组中的每个元素,并对每个元素执行回调函数。
-
是否改变原数组:不会改变原数组。
-
返回值:
undefined
。
1.1.1 基本用法
const arr = [1, 2, 3];
arr.forEach((item) => console.log(item * 2));
// 输出:
// 2
// 4
// 6
console.log(arr); // 输出: [1, 2, 3] (原数组未改变)
1.1.2 尝试修改原数组
const arr = [1, 2, 3];
arr.forEach((item, index, array) => {
array[index] = item * 2; // 尝试修改原数组
});
console.log(arr); // 输出: [2, 4, 6] (原数组被修改)
注意:虽然
forEach
本身不会改变原数组,但在回调函数中可以通过索引直接修改原数组(如上面的例子)。
1.1.3 修改对象属性
如果数组中的元素是对象,forEach
可以修改对象的属性:
const arr = [{ value: 1 }, { value: 2 }, { value: 3 }];
arr.forEach((item) => {
item.value *= 2; // 修改对象的属性
});
console.log(arr);
// 输出: [{ value: 2 }, { value: 4 }, { value: 6 }] (对象属性被修改)
1.1.4 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组(除非在回调中显式修改)。 |
返回值 | undefined |
适用场景 | 遍历数组并执行操作,但不修改数组本身。 |
1.2 map
-
作用:遍历数组中的每个元素,并对每个元素执行回调函数,返回一个新数组。
-
是否改变原数组:不会改变原数组。
-
返回值:一个新数组,包含回调函数的返回值。
1.2.1 基本用法
const arr = [1, 2, 3];
const newArr = arr.map((item) => item * 2);
console.log(newArr); // 输出: [2, 4, 6] (新数组)
console.log(arr); // 输出: [1, 2, 3] (原数组未改变)
1.2.2 修改对象属性
const arr = [{ value: 1 }, { value: 2 }, { value: 3 }];
const newArr = arr.map((item) => {
return { value: item.value * 2 }; // 返回新对象
});
console.log(newArr);
// 输出: [{ value: 2 }, { value: 4 }, { value: 6 }] (新数组)
console.log(arr);
// 输出: [{ value: 1 }, { value: 2 }, { value: 3 }] (原数组未改变)
1.2.3 直接修改原数组中的对象
如果回调函数中直接修改原数组中的对象,原数组中的对象会被修改:
const arr = [{ value: 1 }, { value: 2 }, { value: 3 }];
const newArr = arr.map((item) => {
item.value *= 2; // 直接修改原数组中的对象
return item;
});
console.log(newArr);
// 输出: [{ value: 2 }, { value: 4 }, { value: 6 }] (新数组)
console.log(arr);
// 输出: [{ value: 2 }, { value: 4 }, { value: 6 }] (原数组被修改)
注意:虽然
map
本身不会改变原数组,但在回调函数中可以直接修改原数组中的对象(如上面的例子)。
1.2.4 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组(除非在回调中显式修改对象)。 |
返回值 | 一个新数组,包含回调函数的返回值。 |
适用场景 | 遍历数组并生成一个新数组,不修改原数组。 |
3.filter
-
作用:遍历数组中的每个元素,并根据回调函数的返回值过滤元素,返回一个新数组。
-
是否改变原数组:不会改变原数组。
-
返回值:一个新数组,包含通过回调函数测试的元素。
1.3.1 基本用法
const arr = [1, 2, 3, 4, 5];
const newArr = arr.filter((item) => item % 2 === 0); // 过滤出偶数
console.log(newArr); // 输出: [2, 4] (新数组)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
1.3.2 过滤对象数组
如果数组中的元素是对象,filter
可以根据对象的属性进行过滤:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const newArr = arr.filter((item) => item.age > 25); // 过滤出年龄大于 25 的对象
console.log(newArr);
// 输出: [{ name: 'Bob', age: 30 }] (新数组)
console.log(arr);
// 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
1.3.3 直接修改原数组中的对象
如果回调函数中直接修改原数组中的对象,原数组中的对象会被修改:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const newArr = arr.filter((item) => {
item.age += 1; // 直接修改原数组中的对象
return item.age > 25; // 过滤出年龄大于 25 的对象
});
console.log(newArr);
// 输出: [
// { name: 'Alice', age: 26 },
// { name: 'Bob', age: 31 }
// ] (新数组)
console.log(arr);
// 输出: [
// { name: 'Alice', age: 26 },
// { name: 'Bob', age: 31 },
// { name: 'Charlie', age: 21 }
// ] (原数组被修改)
注意:虽然
filter
本身不会改变原数组,但在回调函数中可以直接修改原数组中的对象(如上面的例子)。
1.3.4 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组(除非在回调中显式修改对象)。 |
返回值 | 一个新数组,包含通过回调函数测试的元素。 |
适用场景 | 过滤数组中的元素,生成一个新数组。 |
4.reduce
-
作用:遍历数组中的每个元素,并将结果累积为一个值。
-
是否改变原数组:不会改变原数组。
-
返回值:累积的结果值。
1.4.1 基本用法
const arr = [1, 2, 3, 4];
const sum = arr.reduce((acc, item) => acc + item, 0); // 计算数组元素的和
console.log(sum); // 输出: 10 (累积值)
console.log(arr); // 输出: [1, 2, 3, 4] (原数组未改变)
1.4.2 累积对象属性
如果数组中的元素是对象,reduce
可以累积对象的属性:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const totalAge = arr.reduce((acc, item) => acc + item.age, 0); // 计算年龄总和
console.log(totalAge); // 输出: 75 (累积值)
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
1.4.3 直接修改原数组中的对象
如果回调函数中直接修改原数组中的对象,原数组中的对象会被修改:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const totalAge = arr.reduce((acc, item) => {
item.age += 1; // 直接修改原数组中的对象
return acc + item.age; // 计算年龄总和
}, 0);
console.log(totalAge); // 输出: 78 (累积值)
console.log(arr); // 输出: [
// { name: 'Alice', age: 26 },
// { name: 'Bob', age: 31 },
// { name: 'Charlie', age: 21 }
// ] (原数组被修改)
注意:虽然
reduce
本身不会改变原数组,但在回调函数中可以直接修改原数组中的对象(如上面的例子)。
1.4.4 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组(除非在回调中显式修改对象)。 |
返回值 | 累积的结果值。 |
适用场景 | 将数组中的元素累积为一个值。 |
5.reduceRight
-
作用:从右到左遍历数组中的每个元素,并将结果累积为一个值。
-
是否改变原数组:不会改变原数组。
-
返回值:累积的结果值。
1.5.1 基本用法
const arr = [1, 2, 3, 4];
const sum = arr.reduceRight((acc, item) => acc + item, 0); // 从右到左计算数组元素的和
console.log(sum); // 输出: 10 (累积值)
console.log(arr); // 输出: [1, 2, 3, 4] (原数组未改变)
1.5.2 累积对象属性
如果数组中的元素是对象,reduceRight
可以累积对象的属性:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const totalAge = arr.reduceRight((acc, item) => acc + item.age, 0); // 从右到左计算年龄总和
console.log(totalAge); // 输出: 75 (累积值)
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
1.5.3 直接修改原数组中的对象
如果回调函数中直接修改原数组中的对象,原数组中的对象会被修改:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const totalAge = arr.reduceRight((acc, item) => {
item.age += 1; // 直接修改原数组中的对象
return acc + item.age; // 计算年龄总和
}, 0);
console.log(totalAge); // 输出: 78 (累积值)
console.log(arr); // 输出: [
// { name: 'Alice', age: 26 },
// { name: 'Bob', age: 31 },
// { name: 'Charlie', age: 21 }
// ] (原数组被修改)
注意:虽然
reduceRight
本身不会改变原数组,但在回调函数中可以直接修改原数组中的对象(如上面的例子)。
1.5.4 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组(除非在回调中显式修改对象)。 |
返回值 | 累积的结果值。 |
适用场景 | 从右到左将数组中的元素累积为一个值。 |
2. 查找方法
2.1 find
-
作用:查找数组中第一个满足回调函数测试的元素。
-
是否改变原数组:不会改变原数组。
-
返回值:第一个满足条件的元素,如果找不到则返回
undefined
。
2.1.1 基本用法
const arr = [1, 2, 3, 4, 5];
const result = arr.find((item) => item > 3); // 查找第一个大于 3 的元素
console.log(result); // 输出: 4 (找到的元素)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
2.1.2 查找对象数组中的元素
如果数组中的元素是对象,find
可以根据对象的属性进行查找:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const result = arr.find((item) => item.age > 25); // 查找第一个年龄大于 25 的对象
console.log(result); // 输出: { name: 'Bob', age: 30 } (找到的元素)
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
2.1.3 找不到满足条件的元素
如果数组中没有任何元素满足条件,find
会返回 undefined
:
const arr = [1, 2, 3, 4, 5];
const result = arr.find((item) => item > 10); // 查找第一个大于 10 的元素
console.log(result); // 输出: undefined (未找到)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
2.1.4 直接修改原数组中的对象
如果回调函数中直接修改原数组中的对象,原数组中的对象会被修改:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const result = arr.find((item) => {
item.age += 1; // 直接修改原数组中的对象
return item.age > 25; // 查找第一个年龄大于 25 的对象
});
console.log(result); // 输出: { name: 'Alice', age: 26 } (找到的元素)
console.log(arr); // 输出: [
// { name: 'Alice', age: 26 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组被修改)
注意:虽然
find
本身不会改变原数组,但在回调函数中可以直接修改原数组中的对象(如上面的例子)。
2.1.5 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组(除非在回调中显式修改对象)。 |
返回值 | 第一个满足条件的元素,如果找不到则返回 undefined 。 |
适用场景 | 查找数组中第一个满足条件的元素。 |
2.2 findIndex
-
作用:查找数组中第一个满足回调函数测试的元素的索引。
-
是否改变原数组:不会改变原数组。
-
返回值:第一个满足条件的元素的索引,如果找不到则返回
-1
。
2.2.1 基本用法
const arr = [1, 2, 3, 4, 5];
const index = arr.findIndex((item) => item > 3); // 查找第一个大于 3 的元素的索引
console.log(index); // 输出: 3 (找到的索引)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
2.2.2 查找对象数组中的元素索引
如果数组中的元素是对象,findIndex
可以根据对象的属性进行查找:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const index = arr.findIndex((item) => item.age > 25); // 查找第一个年龄大于 25 的对象的索引
console.log(index); // 输出: 1 (找到的索引)
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
2.2.3 找不到满足条件的元素
const arr = [1, 2, 3, 4, 5];
const index = arr.findIndex((item) => item > 10); // 查找第一个大于 10 的元素的索引
console.log(index); // 输出: -1 (未找到)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
2.2.4 直接修改原数组中的对象
如果回调函数中直接修改原数组中的对象,原数组中的对象会被修改:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const index = arr.findIndex((item) => {
item.age += 1; // 直接修改原数组中的对象
return item.age > 25; // 查找第一个年龄大于 25 的对象的索引
});
console.log(index); // 输出: 0 (找到的索引)
console.log(arr); // 输出: [
// { name: 'Alice', age: 26 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组被修改)
注意:虽然
findIndex
本身不会改变原数组,但在回调函数中可以直接修改原数组中的对象(如上面的例子)。
2.2.5 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组(除非在回调中显式修改对象)。 |
返回值 | 第一个满足条件的元素的索引,如果找不到则返回 -1 。 |
适用场景 | 查找数组中第一个满足条件的元素的索引。 |
2.3 indexOf
-
作用:查找数组中指定元素的第一个索引。
-
是否改变原数组:不会改变原数组。
-
返回值:指定元素的第一个索引,如果找不到则返回
-1
。
2.3.1 基本用法
const arr = [1, 2, 3, 4, 5];
const index = arr.indexOf(3); // 查找元素 3 的索引
console.log(index); // 输出: 2 (找到的索引)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
2.3.2 查找不存在的元素
如果数组中不存在指定元素,indexOf
会返回 -1
:
const arr = [1, 2, 3, 4, 5];
const index = arr.indexOf(10); // 查找元素 10 的索引
console.log(index); // 输出: -1 (未找到)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
2.3.3 查找对象的索引
indexOf
使用严格相等(===
)来比较元素,因此对于对象,只有当引用相同时才会返回索引:
const obj = { name: 'Alice' };
const arr = [{ name: 'Bob' }, obj, { name: 'Charlie' }];
const index = arr.indexOf(obj); // 查找对象的索引
console.log(index); // 输出: 1 (找到的索引)
console.log(arr); // 输出: [
// { name: 'Bob' },
// { name: 'Alice' },
// { name: 'Charlie' }
// ] (原数组未改变)
2.3.4 查找 NaN
indexOf
无法查找 NaN
,因为 NaN
与任何值(包括自身)都不相等:
const arr = [1, 2, NaN, 4, 5];
const index = arr.indexOf(NaN); // 查找 NaN 的索引
console.log(index); // 输出: -1 (未找到)
console.log(arr); // 输出: [1, 2, NaN, 4, 5] (原数组未改变)
注意:如果需要查找 NaN
,可以使用 findIndex
方法:
const arr = [1, 2, NaN, 4, 5];
const index = arr.findIndex((item) => Number.isNaN(item));
console.log(index); // 输出: 2
2.3.5 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 指定元素的第一个索引,如果找不到则返回 -1 。 |
适用场景 | 查找数组中指定元素的索引。 |
2.4 lastIndexOf
-
作用:查找数组中指定元素的最后一个索引。
-
是否改变原数组:不会改变原数组。
-
返回值:指定元素的最后一个索引,如果找不到则返回
-1
。
2.4.1 基本用法
const arr = [1, 2, 3, 4, 3, 5];
const index = arr.lastIndexOf(3); // 查找元素 3 的最后一个索引
console.log(index); // 输出: 4 (找到的索引)
console.log(arr); // 输出: [1, 2, 3, 4, 3, 5] (原数组未改变)
2.4.2 查找不存在的元素
如果数组中不存在指定元素,lastIndexOf
会返回 -1
:
const arr = [1, 2, 3, 4, 5];
const index = arr.lastIndexOf(10); // 查找元素 10 的最后一个索引
console.log(index); // 输出: -1 (未找到)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
2.4.3 查找对象的索引
lastIndexOf
使用严格相等(===
)来比较元素,因此对于对象,只有当引用相同时才会返回索引:
const obj = { name: 'Alice' };
const arr = [{ name: 'Bob' }, obj, { name: 'Charlie' }, obj];
const index = arr.lastIndexOf(obj); // 查找对象的最后一个索引
console.log(index); // 输出: 3 (找到的索引)
console.log(arr); // 输出: [
// { name: 'Bob' },
// { name: 'Alice' },
// { name: 'Charlie' },
// { name: 'Alice' }
// ] (原数组未改变)
2.4.4 查找 NaN
lastIndexOf
无法查找 NaN
,因为 NaN
与任何值(包括自身)都不相等:
const arr = [1, 2, NaN, 4, NaN, 5];
const index = arr.lastIndexOf(NaN); // 查找 NaN 的最后一个索引
console.log(index); // 输出: -1 (未找到)
console.log(arr); // 输出: [1, 2, NaN, 4, NaN, 5] (原数组未改变)
注意:如果需要查找 NaN
,可以使用 findIndex
方法:
const arr = [1, 2, NaN, 4, NaN, 5];
const index = arr.findIndex((item, i) => Number.isNaN(item) && i === arr.lastIndexOf(item));
console.log(index); // 输出: 4
2.4.5 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 指定元素的最后一个索引,如果找不到则返回 -1 。 |
适用场景 | 查找数组中指定元素的最后一个索引。 |
2.5 includes
的行为
-
作用:判断数组是否包含指定元素。
-
是否改变原数组:不会改变原数组。
-
返回值:如果数组包含指定元素,则返回
true
;否则返回false
。
2.5.1 基本用法
const arr = [1, 2, 3, 4, 5];
const hasThree = arr.includes(3); // 判断数组是否包含元素 3
console.log(hasThree); // 输出: true
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
2.5.2 查找不存在的元素
如果数组中不存在指定元素,includes
会返回 false
:
const arr = [1, 2, 3, 4, 5];
const hasTen = arr.includes(10); // 判断数组是否包含元素 10
console.log(hasTen); // 输出: false
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
3. 查找对象的元素
includes
使用严格相等(===
)来比较元素,因此对于对象,只有当引用相同时才会返回 true
:
const obj = { name: 'Alice' };
const arr = [{ name: 'Bob' }, obj, { name: 'Charlie' }];
const hasObj = arr.includes(obj); // 判断数组是否包含对象
console.log(hasObj); // 输出: true
console.log(arr); // 输出: [
// { name: 'Bob' },
// { name: 'Alice' },
// { name: 'Charlie' }
// ] (原数组未改变)
4. 查找 NaN
includes
可以查找 NaN
,因为它专门处理了 NaN
的情况:
const arr = [1, 2, NaN, 4, 5];
const hasNaN = arr.includes(NaN); // 判断数组是否包含 NaN
console.log(hasNaN); // 输出: true
console.log(arr); // 输出: [1, 2, NaN, 4, 5] (原数组未改变)
总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 如果数组包含指定元素,则返回 true ;否则返回 false 。 |
适用场景 | 判断数组是否包含指定元素。 |
3. 操作方法
3.1 concat
-
作用:合并两个或多个数组。
-
是否改变原数组:不会改变原数组。
-
返回值:一个新数组,包含原数组和传入的数组或值。
3.1.1 基本用法
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const newArr = arr1.concat(arr2); // 合并 arr1 和 arr2
console.log(newArr); // 输出: [1, 2, 3, 4, 5, 6] (新数组)
console.log(arr1); // 输出: [1, 2, 3] (原数组未改变)
console.log(arr2); // 输出: [4, 5, 6] (原数组未改变)
3.1.2 合并多个数组
concat
可以一次合并多个数组:
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [5, 6];
const newArr = arr1.concat(arr2, arr3); // 合并 arr1、arr2 和 arr3
console.log(newArr); // 输出: [1, 2, 3, 4, 5, 6] (新数组)
console.log(arr1); // 输出: [1, 2] (原数组未改变)
console.log(arr2); // 输出: [3, 4] (原数组未改变)
console.log(arr3); // 输出: [5, 6] (原数组未改变)
3.1.3 合并数组和值
concat
不仅可以合并数组,还可以合并数组和值:
const arr = [1, 2, 3];
const newArr = arr.concat(4, 5); // 合并数组和值
console.log(newArr); // 输出: [1, 2, 3, 4, 5] (新数组)
console.log(arr); // 输出: [1, 2, 3] (原数组未改变)
3.1.4 合并嵌套数组
concat
不会递归扁平化嵌套数组:
const arr1 = [1, 2];
const arr2 = [3, [4, 5]];
const newArr = arr1.concat(arr2); // 合并 arr1 和 arr2
console.log(newArr); // 输出: [1, 2, 3, [4, 5]] (新数组)
console.log(arr1); // 输出: [1, 2] (原数组未改变)
console.log(arr2); // 输出: [3, [4, 5]] (原数组未改变)
注意:如果需要扁平化嵌套数组,可以使用 flat
方法:
const arr1 = [1, 2];
const arr2 = [3, [4, 5]];
const newArr = arr1.concat(arr2).flat();
console.log(newArr); // 输出: [1, 2, 3, 4, 5]
3.1.5 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 一个新数组,包含原数组和传入的数组或值。 |
适用场景 | 合并两个或多个数组。 |
3.2 slice
的行为
-
作用:提取数组的一部分。
-
是否改变原数组:不会改变原数组。
-
返回值:一个新数组,包含提取的元素。
3.2.1 基本用法
const arr = [1, 2, 3, 4, 5];
const newArr = arr.slice(1, 3); // 提取索引 1 到 3(不包括 3)的元素
console.log(newArr); // 输出: [2, 3] (新数组)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
3.2.2 省略结束位置
如果省略结束位置,slice
会提取从开始位置到数组末尾的所有元素:
const arr = [1, 2, 3, 4, 5];
const newArr = arr.slice(2); // 提取索引 2 到末尾的元素
console.log(newArr); // 输出: [3, 4, 5] (新数组)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
3.3.3 负数索引
slice
支持负数索引,表示从数组末尾开始计算:
const arr = [1, 2, 3, 4, 5];
const newArr = arr.slice(-3, -1); // 提取倒数第 3 个到倒数第 1 个(不包括倒数第 1 个)的元素
console.log(newArr); // 输出: [3, 4] (新数组)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
3.3.4 提取整个数组
如果不传递任何参数,slice
会返回原数组的浅拷贝:
const arr = [1, 2, 3, 4, 5];
const newArr = arr.slice(); // 提取整个数组
console.log(newArr); // 输出: [1, 2, 3, 4, 5] (新数组)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
3.3.5 提取对象数组
slice
也可以用于提取对象数组的一部分:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const newArr = arr.slice(1, 3); // 提取索引 1 到 3(不包括 3)的元素
console.log(newArr); // 输出: [
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (新数组)
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
3.3.6 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 一个新数组,包含提取的元素。 |
适用场景 | 提取数组的一部分。 |
3.3 splice
-
作用:删除、替换或添加数组中的元素。
-
是否改变原数组:会改变原数组。
-
返回值:被删除的元素组成的数组。
3.3.1 删除元素
const arr = [1, 2, 3, 4, 5];
const removed = arr.splice(1, 2); // 从索引 1 开始删除 2 个元素
console.log(removed); // 输出: [2, 3] (被删除的元素)
console.log(arr); // 输出: [1, 4, 5] (原数组被修改)
3.3.2 替换元素
const arr = [1, 2, 3, 4, 5];
const removed = arr.splice(1, 2, 6, 7); // 从索引 1 开始删除 2 个元素,并插入 6 和 7
console.log(removed); // 输出: [2, 3] (被删除的元素)
console.log(arr); // 输出: [1, 6, 7, 4, 5] (原数组被修改)
3.3.3 添加元素
const arr = [1, 2, 3, 4, 5];
const removed = arr.splice(2, 0, 6, 7); // 从索引 2 开始删除 0 个元素,并插入 6 和 7
console.log(removed); // 输出: [] (没有元素被删除)
console.log(arr); // 输出: [1, 2, 6, 7, 3, 4, 5] (原数组被修改)
3.3.4 负数索引
splice
支持负数索引,表示从数组末尾开始计算:
const arr = [1, 2, 3, 4, 5];
const removed = arr.splice(-2, 2); // 从倒数第 2 个元素开始删除 2 个元素
console.log(removed); // 输出: [4] (被删除的元素)
console.log(arr); // 输出: [1, 2, 3] (原数组被修改)
3.3.5 删除所有元素
如果不传递删除数量,splice
会删除从开始位置到数组末尾的所有元素:
const arr = [1, 2, 3, 4, 5];
const removed = arr.splice(2); // 从索引 2 开始删除所有元素
console.log(removed); // 输出: [3, 4, 5] (被删除的元素)
console.log(arr); // 输出: [1, 2] (原数组被修改)
3.3.6 替换对象数组中的元素
splice
也可以用于替换对象数组中的元素:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const removed = arr.splice(1, 1, { name: 'David', age: 35 }); // 替换索引 1 的元素
console.log(removed); // 输出: [{ name: 'Bob', age: 30 }] (被删除的元素)
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'David', age: 35 },
// { name: 'Charlie', age: 20 }
// ] (原数组被修改)
3.3.7 总结
特性 | 说明 |
---|---|
是否改变原数组 | 会改变原数组。 |
返回值 | 被删除的元素组成的数组。 |
适用场景 | 删除、替换或添加数组中的元素。 |
3.4 join
-
作用:将数组中的所有元素连接成一个字符串。
-
是否改变原数组:不会改变原数组。
-
返回值:连接后的字符串。
3.4.1 基本用法
const arr = [1, 2, 3, 4, 5];
const str = arr.join(); // 使用默认分隔符(逗号)连接数组元素
console.log(str); // 输出: "1,2,3,4,5" (连接后的字符串)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
3.4.2 自定义分隔符
可以传递一个分隔符参数,指定连接数组元素时使用的分隔符:
const arr = [1, 2, 3, 4, 5];
const str = arr.join('-'); // 使用 "-" 连接数组元素
console.log(str); // 输出: "1-2-3-4-5" (连接后的字符串)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
3.4.3 空分隔符
如果传递空字符串作为分隔符,数组元素将直接连接在一起:
const arr = [1, 2, 3, 4, 5];
const str = arr.join(''); // 使用空字符串连接数组元素
console.log(str); // 输出: "12345" (连接后的字符串)
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
3.4.4 包含对象的数组
如果数组中的元素是对象,join
会将对象转换为字符串(通常是 [object Object]
):
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const str = arr.join(', '); // 使用 ", " 连接数组元素
console.log(str); // 输出: "[object Object], [object Object], [object Object]" (连接后的字符串)
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
3.4.5 包含 null
或 undefined
的数组
如果数组中的元素是 null
或 undefined
,join
会将它们转换为空字符串:
const arr = [1, null, 3, undefined, 5];
const str = arr.join('-'); // 使用 "-" 连接数组元素
console.log(str); // 输出: "1--3--5" (连接后的字符串)
console.log(arr); // 输出: [1, null, 3, undefined, 5] (原数组未改变)
3.4.6 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 连接后的字符串。 |
适用场景 | 将数组中的元素连接成一个字符串。 |
4. 排序和反转
4.1 sort
-
作用:对数组中的元素进行排序。
-
是否改变原数组:会改变原数组。
-
返回值:排序后的数组。
4.1.1 基本用法
默认情况下,sort
会将数组元素转换为字符串,然后按字典序排序:
const arr = [3, 1, 4, 1, 5, 9];
arr.sort(); // 默认排序
console.log(arr); // 输出: [1, 1, 3, 4, 5, 9] (排序后的数组)
4.4.2 自定义排序规则
可以传递一个比较函数,指定排序规则:
const arr = [3, 1, 4, 1, 5, 9];
arr.sort((a, b) => a - b); // 按升序排序
console.log(arr); // 输出: [1, 1, 3, 4, 5, 9] (排序后的数组)
4.1.3 降序排序
通过修改比较函数,可以实现降序排序:
const arr = [3, 1, 4, 1, 5, 9];
arr.sort((a, b) => b - a); // 按降序排序
console.log(arr); // 输出: [9, 5, 4, 3, 1, 1] (排序后的数组)
4.1.4 排序对象数组
如果数组中的元素是对象,可以根据对象的属性进行排序:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
arr.sort((a, b) => a.age - b.age); // 按 age 升序排序
console.log(arr); // 输出: [
// { name: 'Charlie', age: 20 },
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 }
// ] (排序后的数组)
4.1.5 排序字符串数组
默认情况下,sort
会按字典序排序字符串数组:
const arr = ['banana', 'apple', 'cherry'];
arr.sort(); // 默认排序
console.log(arr); // 输出: ["apple", "banana", "cherry"] (排序后的数组)
4.1.6 排序包含 null
或 undefined
的数组
如果数组中的元素是 null
或 undefined
,sort
会将它们放在数组的末尾:
const arr = [3, null, 1, undefined, 5];
arr.sort((a, b) => {
if (a == null) return 1; // 将 null 和 undefined 放在末尾
if (b == null) return -1;
return a - b; // 按升序排序
});
console.log(arr); // 输出: [1, 3, 5, null, undefined] (排序后的数组)
4.1.7 总结
特性 | 说明 |
---|---|
是否改变原数组 | 会改变原数组。 |
返回值 | 排序后的数组。 |
适用场景 | 对数组中的元素进行排序。 |
4.2 reverse
-
作用:反转数组中的元素顺序。
-
是否改变原数组:会改变原数组。
-
返回值:反转后的数组。
4.2.1 基本用法
const arr = [1, 2, 3, 4, 5];
arr.reverse(); // 反转数组
console.log(arr); // 输出: [5, 4, 3, 2, 1] (反转后的数组)
4.2.2 反转字符串数组
reverse
也可以用于反转字符串数组:
const arr = ['apple', 'banana', 'cherry'];
arr.reverse(); // 反转数组
console.log(arr); // 输出: ["cherry", "banana", "apple"] (反转后的数组)
4.2.3 反转对象数组
如果数组中的元素是对象,reverse
会反转对象的顺序:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
arr.reverse(); // 反转数组
console.log(arr); // 输出: [
// { name: 'Charlie', age: 20 },
// { name: 'Bob', age: 30 },
// { name: 'Alice', age: 25 }
// ] (反转后的数组)
4.2.4 反转包含 null
或 undefined
的数组
如果数组中的元素是 null
或 undefined
,reverse
会反转它们的顺序:
const arr = [1, null, 3, undefined, 5];
arr.reverse(); // 反转数组
console.log(arr); // 输出: [5, undefined, 3, null, 1] (反转后的数组)
4.2.5 总结
特性 | 说明 |
---|---|
是否改变原数组 | 会改变原数组。 |
返回值 | 反转后的数组。 |
适用场景 | 反转数组中的元素顺序。 |
5. 其他方法
5.1 every
-
作用:测试数组中的所有元素是否都满足指定条件。
-
是否改变原数组:不会改变原数组。
-
返回值:如果所有元素都满足条件,则返回
true
;否则返回false
。
5.1.1 基本用法
const arr = [1, 2, 3, 4, 5];
const allPositive = arr.every((item) => item > 0); // 测试所有元素是否都大于 0
console.log(allPositive); // 输出: true
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
5.1.2 测试部分元素
如果数组中有一个元素不满足条件,every
会立即返回 false
:
const arr = [1, 2, 3, 4, 5];
const allEven = arr.every((item) => item % 2 === 0); // 测试所有元素是否都是偶数
console.log(allEven); // 输出: false
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
5.1.3 测试对象数组
如果数组中的元素是对象,every
可以根据对象的属性进行测试:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const allAdults = arr.every((item) => item.age >= 18); // 测试所有元素是否都是成年人
console.log(allAdults); // 输出: true
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
5.1.4 测试空数组
如果数组为空,every
会返回 true
:
const arr = [];
const allPositive = arr.every((item) => item > 0); // 测试所有元素是否都大于 0
console.log(allPositive); // 输出: true
console.log(arr); // 输出: [] (原数组未改变)
5.1.5 测试包含 null
或 undefined
的数组
如果数组中的元素是 null
或 undefined
,every
会根据回调函数的返回值进行测试:
const arr = [1, null, 3, undefined, 5];
const allDefined = arr.every((item) => item != null); // 测试所有元素是否都非 null 或 undefined
console.log(allDefined); // 输出: false
console.log(arr); // 输出: [1, null, 3, undefined, 5] (原数组未改变)
5.1.6 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 如果所有元素都满足条件,则返回 true ;否则返回 false 。 |
适用场景 | 测试数组中的所有元素是否都满足指定条件。 |
5.2 some
-
作用:测试数组中是否至少有一个元素满足指定条件。
-
是否改变原数组:不会改变原数组。
-
返回值:如果至少有一个元素满足条件,则返回
true
;否则返回false
。
5.2.1 基本用法
const arr = [1, 2, 3, 4, 5];
const hasEven = arr.some((item) => item % 2 === 0); // 测试是否有偶数
console.log(hasEven); // 输出: true
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
5.2.2 测试部分元素
如果数组中有一个元素满足条件,some
会立即返回 true
:
const arr = [1, 2, 3, 4, 5];
const hasNegative = arr.some((item) => item < 0); // 测试是否有负数
console.log(hasNegative); // 输出: false
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
5.2.3 测试对象数组
如果数组中的元素是对象,some
可以根据对象的属性进行测试:
const arr = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
const hasTeenager = arr.some((item) => item.age < 18); // 测试是否有未成年人
console.log(hasTeenager); // 输出: false
console.log(arr); // 输出: [
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 },
// { name: 'Charlie', age: 20 }
// ] (原数组未改变)
5.2.4 测试空数组
如果数组为空,some
会返回 false
:
const arr = [];
const hasPositive = arr.some((item) => item > 0); // 测试是否有正数
console.log(hasPositive); // 输出: false
console.log(arr); // 输出: [] (原数组未改变)
5.2.5 测试包含 null
或 undefined
的数组
如果数组中的元素是 null
或 undefined
,some
会根据回调函数的返回值进行测试:
const arr = [1, null, 3, undefined, 5];
const hasNull = arr.some((item) => item == null); // 测试是否有 null 或 undefined
console.log(hasNull); // 输出: true
console.log(arr); // 输出: [1, null, 3, undefined, 5] (原数组未改变)
5.2.6 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 如果至少有一个元素满足条件,则返回 true ;否则返回 false 。 |
适用场景 | 测试数组中是否至少有一个元素满足指定条件。 |
5.3 flat
-
作用:将嵌套数组展平为一维数组,可以指定展平的深度。
-
是否改变原数组:不会改变原数组。
-
返回值:返回一个新数组,新数组是原数组展平后的结果。
5.3.1 基本用法
默认展平深度为 1:
const arr = [1, 2, [3, 4]];
const flattened = arr.flat();
console.log(flattened); // 输出: [1, 2, 3, 4]
console.log(arr); // 输出: [1, 2, [3, 4]] (原数组未改变)
5.3.2 指定展平深度
可以指定展平的深度:
const arr = [1, 2, [3, 4, [5, 6]]];
const flattened = arr.flat(2);
console.log(flattened); // 输出: [1, 2, 3, 4, 5, 6]
console.log(arr); // 输出: [1, 2, [3, 4, [5, 6]]] (原数组未改变)
5.3.3 完全展平
使用 Infinity
可以完全展平数组,无论嵌套多深:
const arr = [1, 2, [3, 4, [5, 6, [7, 8]]]];
const flattened = arr.flat(Infinity);
console.log(flattened); // 输出: [1, 2, 3, 4, 5, 6, 7, 8]
console.log(arr); // 输出: [1, 2, [3, 4, [5, 6, [7, 8]]]] (原数组未改变)
5.3.4 处理空项
flat()
会自动移除数组中的空项:
const arr = [1, 2, , 4, 5];
const flattened = arr.flat();
console.log(flattened); // 输出: [1, 2, 4, 5]
console.log(arr); // 输出: [1, 2, , 4, 5] (原数组未改变)
5.3.5 处理非嵌套数组
如果数组中没有嵌套数组,flat()
会返回一个浅拷贝:
const arr = [1, 2, 3, 4, 5];
const flattened = arr.flat();
console.log(flattened); // 输出: [1, 2, 3, 4, 5]
console.log(arr); // 输出: [1, 2, 3, 4, 5] (原数组未改变)
5.3.6 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 返回一个新数组,新数组是原数组展平后的结果。 |
适用场景 | 用于将嵌套数组展平为一维数组,可以指定展平的深度。 |
5.4 flatMap
-
作用:对数组中的每个元素执行映射操作,然后将结果展平一层。
-
是否改变原数组:不会改变原数组。
-
返回值:返回一个新数组,新数组是映射并展平后的结果。
5.4.1 基本用法
将数组中的每个元素映射为一个新数组,然后展平:
const arr = [1, 2, 3];
const result = arr.flatMap((item) => [item * 2]);
console.log(result); // 输出: [2, 4, 6]
console.log(arr); // 输出: [1, 2, 3] (原数组未改变)
5.4.2 映射为多个元素
将数组中的每个元素映射为多个元素,然后展平:
const arr = [1, 2, 3];
const result = arr.flatMap((item) => [item, item * 2]);
console.log(result); // 输出: [1, 2, 2, 4, 3, 6]
console.log(arr); // 输出: [1, 2, 3] (原数组未改变)
5.4.3 处理嵌套数组
如果映射的结果是嵌套数组,flatMap()
会自动展平一层:
const arr = [1, 2, 3];
const result = arr.flatMap((item) => [[item * 2]]);
console.log(result); // 输出: [[2], [4], [6]] (只展平一层)
console.log(arr); // 输出: [1, 2, 3] (原数组未改变)
5.4.4 结合字符串操作
将字符串数组中的每个字符串拆分为字符数组,然后展平:
const arr = ["hello", "world"];
const result = arr.flatMap((str) => str.split(""));
console.log(result); // 输出: ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]
console.log(arr); // 输出: ["hello", "world"] (原数组未改变)
5.4.5 过滤空值
flatMap()
可以用于过滤掉空值,同时展平数组:
const arr = [1, 2, 3, 4];
const result = arr.flatMap((item) => (item % 2 === 0 ? [] : [item]));
console.log(result); // 输出: [1, 3] (过滤掉偶数)
console.log(arr); // 输出: [1, 2, 3, 4] (原数组未改变)
5.4.6 总结
特性 | 说明 |
---|---|
是否改变原数组 | 不会改变原数组。 |
返回值 | 返回一个新数组,新数组是映射并展平后的结果。 |
适用场景 | 用于对数组中的每个元素执行映射操作,并将结果展平一层。 |
5.4.7 flatMap 与 map + flat 的区别
flatMap()
相当于 map()
后接 flat(1)
,但 flatMap()
的性能通常更好,因为它只需要遍历一次数组。
示例对比
const arr = [1, 2, 3];
// 使用 map + flat
const result1 = arr.map((item) => [item * 2]).flat();
console.log(result1); // 输出: [2, 4, 6]
// 使用 flatMap
const result2 = arr.flatMap((item) => [item * 2]);
console.log(result2); // 输出: [2, 4, 6]
注意事项
-
flatMap()
只能展平一层。如果需要更深层次的展平,可以结合flat()
使用。 -
如果映射函数返回的不是数组,
flatMap()
会将其包装为数组后再展平。
总结
数组方法
方法 | 作用 | 示例 |
---|---|---|
forEach | 遍历数组中的每个元素 | [1, 2, 3].forEach(item => console.log(item)) |
map | 返回一个新数组,包含回调函数的返回值 | [1, 2, 3].map(item => item * 2) |
filter | 返回一个新数组,包含通过测试的元素 | [1, 2, 3].filter(item => item % 2 === 0) |
reduce | 将数组元素汇总为单个值 | [1, 2, 3].reduce((acc, item) => acc + item, 0) |
find | 返回第一个通过测试的元素 | [1, 2, 3].find(item => item % 2 === 0) |
findIndex | 返回第一个通过测试的元素的索引 | [1, 2, 3].findIndex(item => item % 2 === 0) |
indexOf | 返回指定元素的第一个索引 | [1, 2, 3].indexOf(2) |
includes | 判断数组是否包含指定元素 | [1, 2, 3].includes(2) |
concat | 合并数组 | [1, 2].concat([3, 4]) |
slice | 返回数组的一部分 | [1, 2, 3, 4].slice(1, 3) |
splice | 修改数组内容 | [1, 2, 3].splice(1, 1, 4) |
join | 将数组元素连接为字符串 | [1, 2, 3].join('-') |
sort | 对数组元素进行排序 | [3, 1, 2].sort((a, b) => a - b) |
reverse | 反转数组元素顺序 | [1, 2, 3].reverse() |
every | 测试所有元素是否通过测试 | [2, 4, 6].every(item => item % 2 === 0) |
some | 测试是否有元素通过测试 | [1, 2, 3].some(item => item % 2 === 0) |
flat | 扁平化嵌套数组 | [1, [2, [3]]].flat(2) |
flatMap | 先映射后扁平化 | [1, 2, 3].flatMap(item => [item, item * 2]) |