JavaScript数组常用的方法有哪些?map、filter、reduce 的区别和使用场景是什么?
JavaScript 数组常用方法
JavaScript 数组有很多实用的方法,以下先简单介绍一些常见的基础方法,再重点讲解 map
、filter
、reduce
这三个高阶函数。
1. 基础常用方法
push()
和 pop()
push()
:就像往一个箱子里放东西,它会把一个或多个元素添加到数组的末尾,然后返回新数组的长度。pop()
:类似于从箱子里拿出最上面的东西,它会移除数组的最后一个元素,并返回这个被移除的元素。
let fruits = ['apple', 'banana'];
// 使用 push() 添加元素
let newLength = fruits.push('cherry');
console.log(newLength); // 输出: 3
console.log(fruits); // 输出: ['apple', 'banana', 'cherry']
// 使用 pop() 移除元素
let removedFruit = fruits.pop();
console.log(removedFruit); // 输出: 'cherry'
console.log(fruits); // 输出: ['apple', 'banana']
unshift()
和 shift()
unshift()
:好比在箱子最前面插入东西,它会把一个或多个元素添加到数组的开头,然后返回新数组的长度。shift()
:如同从箱子最前面拿走东西,它会移除数组的第一个元素,并返回这个被移除的元素。
let numbers = [2, 3];
// 使用 unshift() 添加元素
let newLength2 = numbers.unshift(1);
console.log(newLength2); // 输出: 3
console.log(numbers); // 输出: [1, 2, 3]
// 使用 shift() 移除元素
let removedNumber = numbers.shift();
console.log(removedNumber); // 输出: 1
console.log(numbers); // 输出: [2, 3]
splice()
splice()
就像一个“数组外科医生”,它可以删除、替换或插入元素。它接收三个参数,第一个是开始操作的索引,第二个是要删除的元素个数,后面还可以跟要插入的元素。
let colors = ['red', 'green', 'blue'];
// 删除元素
colors.splice(1, 1);
console.log(colors); // 输出: ['red', 'blue']
// 插入元素
colors.splice(1, 0, 'yellow');
console.log(colors); // 输出: ['red', 'yellow', 'blue']
// 替换元素
colors.splice(1, 1, 'orange');
console.log(colors); // 输出: ['red', 'orange', 'blue']
map
、filter
、reduce
的区别和使用场景
1. map()
- 区别:
map
就像是一个“加工厂”,它会遍历数组中的每个元素,对每个元素执行你提供的函数,然后把处理后的结果组成一个新数组返回。新数组的长度和原数组一样,只是每个元素都经过了处理。 - 使用场景:当你需要对数组中的每个元素进行某种转换时,就可以使用
map
。比如把数组中的每个数字都乘以 2。
let numbers = [1, 2, 3];
// 使用 map 将每个数字乘以 2
let newNumbers = numbers.map(function(num) {
return num * 2;
});
console.log(newNumbers); // 输出: [2, 4, 6]
2. filter()
- 区别:
filter
类似于一个“筛选器”,它会遍历数组中的每个元素,对每个元素执行你提供的函数,根据函数返回的布尔值来决定是否保留该元素。如果返回true
,则该元素会被保留到新数组中;如果返回false
,则该元素会被过滤掉。 - 使用场景:当你需要从数组中筛选出符合某种条件的元素时,就可以使用
filter
。比如从数组中找出所有大于 5 的数字。
let numbers2 = [3, 6, 8, 2];
// 使用 filter 找出大于 5 的数字
let filteredNumbers = numbers2.filter(function(num) {
return num > 5;
});
console.log(filteredNumbers); // 输出: [6, 8]
3. reduce()
- 区别:
reduce
就像一个“累加器”或者“合并器”,它会遍历数组中的每个元素,对每个元素执行你提供的函数,并且会把上一次计算的结果传递给下一次计算。最后返回一个最终的结果。它接收两个参数,第一个是一个回调函数,第二个是初始值(可选)。 - 使用场景:当你需要对数组中的元素进行累加、合并等操作时,就可以使用
reduce
。比如计算数组中所有数字的总和。
let numbers3 = [1, 2, 3, 4];
// 使用 reduce 计算数组元素的总和
let sum = numbers3.reduce(function(accumulator, currentValue) {
return accumulator + currentValue;
}, 0);
console.log(sum); // 输出: 10
总结来说,map
用于元素转换,filter
用于元素筛选,reduce
用于元素合并或累加。
**在实际项目中,map、filter、reduce 方法通常如何搭配使用?
**
在实际项目中,map
、filter
和 reduce
这三个数组方法经常搭配使用,以实现复杂的数据处理和转换。下面通过不同的实际场景示例,展示它们的搭配使用方式。
场景一:数据筛选与转换后求和
假设你有一个电商项目,需要计算所有已付款商品的总价。商品列表是一个包含多个商品对象的数组,每个商品对象有 price
(价格)和 isPaid
(是否付款)两个属性。
// 模拟商品列表
const products = [
{ id: 1, price: 20, isPaid: true },
{ id: 2, price: 30, isPaid: false },
{ id: 3, price: 15, isPaid: true },
{ id: 4, price: 40, isPaid: true }
];
// 步骤 1:使用 filter 筛选出已付款的商品
const paidProducts = products.filter(product => product.isPaid);
// 步骤 2:使用 map 提取已付款商品的价格
const paidPrices = paidProducts.map(product => product.price);
// 步骤 3:使用 reduce 计算已付款商品的总价
const totalPrice = paidPrices.reduce((acc, price) => acc + price, 0);
console.log(totalPrice); // 输出: 75
在这个例子中,首先使用 filter
方法筛选出已付款的商品,得到一个只包含已付款商品的新数组。然后使用 map
方法从这个新数组中提取出每个商品的价格,形成一个只包含价格的数组。最后使用 reduce
方法对这个价格数组进行累加,得到已付款商品的总价。
场景二:数据转换与筛选后统计数量
假设你在开发一个博客系统,需要统计所有发布状态为“已发布”且阅读量大于 100 的文章数量。文章列表是一个包含多个文章对象的数组,每个文章对象有 status
(状态)和 views
(阅读量)两个属性。
// 模拟文章列表
const articles = [
{ title: '文章1', status: 'published', views: 120 },
{ title: '文章2', status: 'draft', views: 80 },
{ title: '文章3', status: 'published', views: 150 },
{ title: '文章4', status: 'published', views: 50 }
];
// 步骤 1:使用 map 转换文章对象为是否符合条件的布尔值
const isQualified = articles.map(article => article.status === 'published' && article.views > 100);
// 步骤 2:使用 filter 筛选出符合条件的布尔值(即 true)
const qualifiedArticles = isQualified.filter(Boolean);
// 步骤 3:使用 reduce 统计符合条件的文章数量
const count = qualifiedArticles.reduce((acc) => acc + 1, 0);
console.log(count); // 输出: 2
这里先使用 map
方法将文章对象转换为布尔值,表示该文章是否符合“已发布且阅读量大于 100”的条件。接着使用 filter
方法筛选出布尔值为 true
的元素,得到一个只包含 true
的数组。最后使用 reduce
方法对这个数组进行累加,统计出符合条件的文章数量。
场景三:数据分组与统计
假设你在处理一个学生成绩数据,需要统计每个班级的总成绩。学生成绩数据是一个包含多个学生对象的数组,每个学生对象有 class
(班级)和 score
(成绩)两个属性。
// 模拟学生成绩数据
const students = [
{ name: '张三', class: 'A', score: 80 },
{ name: '李四', class: 'B', score: 90 },
{ name: '王五', class: 'A', score: 70 },
{ name: '赵六', class: 'B', score: 85 }
];
// 使用 reduce 进行分组和统计
const classScores = students.reduce((acc, student) => {
const { class: className, score } = student;
if (!acc[className]) {
acc[className] = 0;
}
acc[className] += score;
return acc;
}, {});
console.log(classScores); // 输出: { A: 150, B: 175 }
在这个例子中,主要使用 reduce
方法完成数据的分组和统计。reduce
的初始值是一个空对象 {}
,在回调函数中,根据学生的班级对成绩进行分组累加,最终得到每个班级的总成绩。如果需要对每个班级的总成绩进行进一步处理,比如转换为数组形式,可以结合 map
方法:
const classScoreArray = Object.entries(classScores).map(([className, totalScore]) => ({
class: className,
totalScore
}));
console.log(classScoreArray);
// 输出: [ { class: 'A', totalScore: 150 }, { class: 'B', totalScore: 175 } ]
通过以上场景可以看出,map
、filter
和 reduce
方法相互配合,能够高效地完成各种复杂的数据处理任务。在实际应用中,可以根据具体需求灵活组合使用这些方法。
在实际项目中,map、filter、reduce 方法的性能有何区别?
在实际项目中,map
、filter
和 reduce
都是 JavaScript 数组的高阶函数,它们在性能方面存在一些区别,下面从时间复杂度、内存使用、实际应用场景等方面详细分析。
时间复杂度
map
方法:map
方法会遍历数组中的每个元素,对每个元素执行一次提供的回调函数,并将结果存储在一个新数组中。因此,map
方法的时间复杂度是 O ( n ) O(n) O(n),其中 n n n 是数组的长度。因为它只需要对数组进行一次线性遍历。
const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(num => num * num);
filter
方法:filter
方法同样会遍历数组中的每个元素,根据回调函数的返回值决定是否将该元素保留在新数组中。所以,filter
方法的时间复杂度也是 O ( n ) O(n) O(n),需要对数组进行一次完整的遍历。
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(num => num % 2 === 0);
reduce
方法:reduce
方法会对数组中的每个元素执行一次回调函数,并将上一次回调的结果传递给下一次回调。其时间复杂度同样是 O ( n ) O(n) O(n),因为它也需要遍历数组一次。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
内存使用
map
方法:map
方法会创建一个与原数组长度相同的新数组,新数组中的每个元素是原数组对应元素经过处理后的结果。因此,它的内存使用主要取决于原数组的长度和处理后元素的大小。如果处理后的元素大小与原元素相近,那么内存使用会增加与原数组大小相近的空间。
const largeArray = new Array(1000000).fill(1);
const newArray = largeArray.map(num => num * 2);
filter
方法:filter
方法创建的新数组长度通常小于或等于原数组长度,具体取决于过滤条件。如果大部分元素都满足过滤条件,那么内存使用会接近原数组大小;如果只有少数元素满足条件,内存使用会相应减少。
const largeArray = new Array(1000000).fill(1);
const filteredArray = largeArray.filter(num => num % 2 === 0);
reduce
方法:reduce
方法不会创建新数组,而是返回一个单一的值或对象。因此,它的内存使用相对较小,主要取决于最终结果的大小。
const largeArray = new Array(1000000).fill(1);
const sum = largeArray.reduce((acc, num) => acc + num, 0);
实际应用场景对性能的影响
- 简单转换场景:如果只是对数组中的每个元素进行简单的转换,使用
map
方法是最合适的。因为它的逻辑清晰,性能也比较稳定。例如,将数组中的每个数字转换为其平方值。
const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = numbers.map(num => num * num);
- 筛选场景:当需要从数组中筛选出符合特定条件的元素时,使用
filter
方法。它可以避免不必要的元素处理,提高性能。例如,从数组中筛选出所有偶数。
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(num => num % 2 === 0);
- 聚合场景:如果需要对数组元素进行聚合操作,如求和、求平均值等,使用
reduce
方法。它可以在一次遍历中完成聚合,避免多次遍历数组。例如,计算数组中所有元素的总和。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
链式调用时的性能考虑
在实际项目中,经常会链式调用这三个方法。在链式调用时,每次调用都会创建一个新的中间数组(map
和 filter
),这会增加内存使用和处理时间。可以考虑使用 reduce
方法来合并多个操作,减少中间数组的创建,提高性能。
// 链式调用 map 和 filter
const numbers = [1, 2, 3, 4, 5];
const result1 = numbers.map(num => num * 2).filter(num => num > 5);
// 使用 reduce 合并操作
const result2 = numbers.reduce((acc, num) => {
const doubled = num * 2;
if (doubled > 5) {
acc.push(doubled);
}
return acc;
}, []);
综上所述,map
、filter
和 reduce
方法的时间复杂度相同,但在内存使用和适用场景上有所差异。在实际项目中,需要根据具体需求选择合适的方法,以提高代码的性能和效率。
除了 map、filter、reduce 之外,还有哪些常用的数组方法?
除了 map
、filter
、reduce
之外,JavaScript 数组还有许多其他常用的方法,下面为你详细介绍:
1. 元素添加与删除类
push()
和 pop()
push()
:用于在数组的末尾添加一个或多个元素,并返回新的数组长度。
const fruits = ['apple', 'banana'];
const newLength = fruits.push('cherry', 'date');
console.log(fruits); // 输出: ['apple', 'banana', 'cherry', 'date']
console.log(newLength); // 输出: 4
pop()
:用于移除数组的最后一个元素,并返回该元素。
const fruits = ['apple', 'banana', 'cherry'];
const removedFruit = fruits.pop();
console.log(fruits); // 输出: ['apple', 'banana']
console.log(removedFruit); // 输出: 'cherry'
unshift()
和 shift()
unshift()
:在数组的开头添加一个或多个元素,并返回新的数组长度。
const numbers = [2, 3];
const newLength = numbers.unshift(0, 1);
console.log(numbers); // 输出: [0, 1, 2, 3]
console.log(newLength); // 输出: 4
shift()
:移除数组的第一个元素,并返回该元素。
const numbers = [1, 2, 3];
const removedNumber = numbers.shift();
console.log(numbers); // 输出: [2, 3]
console.log(removedNumber); // 输出: 1
splice()
可以用于删除、插入或替换数组中的元素。它接收三个参数:起始索引、要删除的元素个数、要插入的元素(可选)。
const colors = ['red', 'green', 'blue'];
// 删除元素
colors.splice(1, 1);
console.log(colors); // 输出: ['red', 'blue']
// 插入元素
colors.splice(1, 0, 'yellow');
console.log(colors); // 输出: ['red', 'yellow', 'blue']
// 替换元素
colors.splice(1, 1, 'orange');
console.log(colors); // 输出: ['red', 'orange', 'blue']
2. 数组合并与截取类
concat()
用于合并两个或多个数组,并返回一个新数组,原数组不会被修改。
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [5, 6];
const newArray = arr1.concat(arr2, arr3);
console.log(newArray); // 输出: [1, 2, 3, 4, 5, 6]
slice()
用于截取数组的一部分,并返回一个新数组,原数组不会被修改。它接收两个参数:起始索引和结束索引(可选,不包含该索引对应的元素)。
const numbers = [1, 2, 3, 4, 5];
const slicedArray = numbers.slice(1, 3);
console.log(slicedArray); // 输出: [2, 3]
3. 数组查找与排序类
indexOf()
和 lastIndexOf()
indexOf()
:返回指定元素在数组中第一次出现的索引,如果未找到则返回 -1。
const fruits = ['apple', 'banana', 'cherry', 'banana'];
const index = fruits.indexOf('banana');
console.log(index); // 输出: 1
lastIndexOf()
:返回指定元素在数组中最后一次出现的索引,如果未找到则返回 -1。
const fruits = ['apple', 'banana', 'cherry', 'banana'];
const lastIndex = fruits.lastIndexOf('banana');
console.log(lastIndex); // 输出: 3
find()
和 findIndex()
find()
:返回数组中满足提供的测试函数的第一个元素的值,如果没有找到则返回undefined
。
const numbers = [1, 2, 3, 4, 5];
const foundNumber = numbers.find(num => num > 3);
console.log(foundNumber); // 输出: 4
findIndex()
:返回数组中满足提供的测试函数的第一个元素的索引,如果没有找到则返回 -1。
const numbers = [1, 2, 3, 4, 5];
const foundIndex = numbers.findIndex(num => num > 3);
console.log(foundIndex); // 输出: 3
sort()
用于对数组的元素进行排序,默认按照字符串的 Unicode 编码进行排序。可以传入一个比较函数来指定排序规则。
const numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
numbers.sort((a, b) => a - b);
console.log(numbers); // 输出: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
4. 数组转换与迭代类
join()
将数组的所有元素连接成一个字符串,并返回该字符串。可以指定连接符,默认为逗号。
const fruits = ['apple', 'banana', 'cherry'];
const fruitString = fruits.join(' - ');
console.log(fruitString); // 输出: 'apple - banana - cherry'
reverse()
用于颠倒数组中元素的顺序,原数组会被修改。
const numbers = [1, 2, 3, 4, 5];
numbers.reverse();
console.log(numbers); // 输出: [5, 4, 3, 2, 1]
forEach()
对数组的每个元素执行一次提供的函数,没有返回值。
const numbers = [1, 2, 3];
numbers.forEach(num => {
console.log(num * 2);
});
// 输出: 2
// 输出: 4
// 输出: 6
concat() 方法与 push() 方法有什么区别?
concat()
和 push()
都是 JavaScript 数组中用于添加元素的方法,但它们在功能、使用方式、对原数组的影响以及返回值等方面存在明显区别,下面为你详细介绍:
1. 功能和使用方式
concat()
方法:主要用于合并两个或多个数组,它可以接收数组或者单个值作为参数,将这些参数中的元素合并到一个新数组中。concat()
方法不会修改原数组,而是返回一个新的合并后的数组。
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = 5;
// 合并数组和单个值
const newArray = arr1.concat(arr2, arr3);
console.log(newArray); // 输出: [1, 2, 3, 4, 5]
console.log(arr1); // 输出: [1, 2],原数组未被修改
push()
方法:用于在数组的末尾添加一个或多个元素。它直接修改调用该方法的原数组,并且返回新数组的长度。
const arr = [1, 2];
const newLength = arr.push(3, 4);
console.log(arr); // 输出: [1, 2, 3, 4],原数组被修改
console.log(newLength); // 输出: 4
2. 对原数组的影响
concat()
方法:不改变原数组,它只是创建并返回一个新的数组,这个新数组包含了原数组和传入参数中的所有元素。原数组保持不变,这在需要保留原始数据的场景中非常有用。
const originalArray = [1, 2];
const anotherArray = [3, 4];
const combinedArray = originalArray.concat(anotherArray);
console.log(originalArray); // 输出: [1, 2]
push()
方法:会直接修改调用它的数组,将新元素添加到原数组的末尾。这意味着原数组的内容会发生改变。
const originalArray = [1, 2];
originalArray.push(3);
console.log(originalArray); // 输出: [1, 2, 3]
3. 返回值
concat()
方法:返回一个新的数组,这个新数组是原数组和传入参数合并后的结果。
const arr1 = [1, 2];
const arr2 = [3, 4];
const result = arr1.concat(arr2);
console.log(result); // 输出: [1, 2, 3, 4]
push()
方法:返回添加元素后数组的新长度。
const arr = [1, 2];
const length = arr.push(3);
console.log(length); // 输出: 3
4. 处理多维数组的方式
concat()
方法:对于传入的数组参数,它会将其元素展开并添加到新数组中,而不是将整个数组作为一个元素添加。
const arr1 = [1, 2];
const arr2 = [3, 4];
const result = arr1.concat(arr2);
console.log(result); // 输出: [1, 2, 3, 4]
push()
方法:如果传入的是一个数组,它会将整个数组作为一个元素添加到原数组的末尾。
const arr = [1, 2];
const anotherArr = [3, 4];
arr.push(anotherArr);
console.log(arr); // 输出: [1, 2, [3, 4]]
综上所述,concat()
适用于需要合并数组且不改变原数组的场景,而 push()
适用于直接在原数组末尾添加元素并获取新数组长度的场景。
**slice() 和 splice() 方法有什么不同?
**
slice()
和 splice()
是 JavaScript 数组中用于处理数组元素的两个方法,它们在功能、使用方式、对原数组的影响等方面存在明显差异,以下是详细对比:
1. 功能用途
slice()
方法:主要用于从原数组中提取一部分元素,创建并返回一个新数组,就像用刀从一块蛋糕上切下一部分,原蛋糕(原数组)不会被改变。常用于获取数组的子集,比如获取数组的前几个元素、中间一段元素等。splice()
方法:功能更强大且灵活,它可以用于删除、插入或替换数组中的元素,相当于对原数组进行“手术”,会直接修改原数组。常用于需要对数组进行元素的增删改操作的场景。
2. 语法和参数
slice()
方法:- 语法:
arr.slice([begin[, end]])
- 参数:
begin
(可选):提取起始位置的索引,默认为 0。如果为负数,则从数组末尾开始计算。end
(可选):提取结束位置的索引(不包含该索引对应的元素)。如果省略,则提取到数组末尾;如果为负数,则从数组末尾开始计算。
- 语法:
const fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
const slicedFruits = fruits.slice(1, 3);
console.log(slicedFruits); // 输出: ['banana', 'cherry']
console.log(fruits); // 输出: ['apple', 'banana', 'cherry', 'date', 'elderberry'],原数组未改变
splice()
方法:- 语法:
arr.splice(start[, deleteCount[, item1[, item2[, ...]]]])
- 参数:
start
:操作起始位置的索引。deleteCount
(可选):要删除的元素个数。如果省略,则从start
位置开始删除到数组末尾;如果为 0,则不删除元素。item1, item2, ...
(可选):要插入到数组中的元素,从start
位置开始插入。
- 语法:
const fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
// 删除元素
const removedFruits = fruits.splice(1, 2);
console.log(removedFruits); // 输出: ['banana', 'cherry']
console.log(fruits); // 输出: ['apple', 'date', 'elderberry'],原数组被修改
// 插入元素
fruits.splice(1, 0, 'fig', 'grape');
console.log(fruits); // 输出: ['apple', 'fig', 'grape', 'date', 'elderberry']
// 替换元素
fruits.splice(2, 1, 'honeydew');
console.log(fruits); // 输出: ['apple', 'fig', 'honeydew', 'date', 'elderberry']
3. 对原数组的影响
slice()
方法:不会修改原数组,它只是从原数组中提取元素并返回一个新数组,原数组保持不变。这在需要保留原始数据,同时获取部分数据的场景中非常有用。splice()
方法:会直接修改原数组,根据传入的参数进行元素的删除、插入或替换操作。原数组的内容会发生改变,适用于需要对数组进行实时修改的场景。
4. 返回值
slice()
方法:返回一个新数组,包含从原数组中提取的元素。splice()
方法:返回一个数组,包含从原数组中删除的元素。如果没有删除元素,则返回一个空数组。
综上所述,slice()
主要用于提取数组元素,不改变原数组;而 splice()
用于对数组进行增删改操作,会改变原数组。在实际使用中,应根据具体需求选择合适的方法。
在实际项目中,map、filter、reduce 如何选用方法?
在实际项目中,map
、filter
和 reduce
是 JavaScript 数组非常实用的高阶函数,它们各自有独特的用途,选用时需要依据具体的业务需求,下面详细介绍选用这些方法的思路和实际场景示例。
1. map
方法
适用场景
当你需要对数组中的每个元素进行相同的转换操作,并且希望得到一个新数组,新数组的长度与原数组相同,只是元素的值经过了处理,这时就可以使用 map
方法。简单来说,就是“一个换一个”的操作。
示例
在一个电商项目中,有一个商品价格数组,需要将每个商品的价格增加 10%。
const prices = [100, 200, 300];
const newPrices = prices.map(price => price * 1.1);
console.log(newPrices);
// 输出: [110, 220, 330]
这里使用 map
方法对 prices
数组中的每个元素乘以 1.1,得到一个新的 newPrices
数组。
2. filter
方法
适用场景
当你需要从数组中筛选出符合特定条件的元素,形成一个新数组,新数组的长度可能小于原数组,这时就适合使用 filter
方法。可以把它想象成一个“筛子”,只让符合条件的元素通过。
示例
在一个学生成绩管理系统中,有一个学生成绩数组,需要筛选出成绩大于 80 分的学生。
const scores = [70, 85, 90, 60, 88];
const highScores = scores.filter(score => score > 80);
console.log(highScores);
// 输出: [85, 90, 88]
这里使用 filter
方法筛选出 scores
数组中大于 80 的元素,组成新的 highScores
数组。
3. reduce
方法
适用场景
reduce
方法适用于对数组元素进行聚合操作,将数组中的多个元素合并成一个单一的值或对象。常见的聚合操作包括求和、求平均值、统计数量、分组等。
示例
- 求和:计算一个数组中所有数字的总和。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum);
// 输出: 15
这里 reduce
方法从初始值 0 开始,依次将数组中的元素累加到 acc
中,最终得到总和。
- 分组:有一个学生信息数组,需要根据学生的班级进行分组。
const students = [
{ name: '张三', class: 'A' },
{ name: '李四', class: 'B' },
{ name: '王五', class: 'A' }
];
const groupedStudents = students.reduce((acc, student) => {
const className = student.class;
if (!acc[className]) {
acc[className] = [];
}
acc[className].push(student);
return acc;
}, {});
console.log(groupedStudents);
// 输出: { A: [ { name: '张三', class: 'A' }, { name: '王五', class: 'A' } ], B: [ { name: '李四', class: 'B' } ] }
这里使用 reduce
方法将学生按班级分组,最终得到一个对象,对象的键是班级名,值是该班级的学生数组。
4. 组合使用
在实际项目中,还可能会组合使用这三个方法。例如,先使用 filter
筛选出符合条件的元素,再使用 map
对筛选后的元素进行转换,最后使用 reduce
进行聚合。
示例
有一个商品数组,需要筛选出价格大于 50 的商品,将这些商品的价格增加 10%,然后计算这些商品的总价。
const products = [
{ name: '商品1', price: 30 },
{ name: '商品2', price: 60 },
{ name: '商品3', price: 80 }
];
const totalPrice = products
.filter(product => product.price > 50)
.map(product => product.price * 1.1)
.reduce((acc, price) => acc + price, 0);
console.log(totalPrice);
// 输出: 154
这里先使用 filter
筛选出价格大于 50 的商品,再用 map
对筛选后的商品价格增加 10%,最后用 reduce
计算总价。
综上所述,选用 map
、filter
还是 reduce
方法,关键在于明确业务需求是进行元素转换、筛选还是聚合,以及是否需要组合使用这些方法来完成更复杂的操作。