JavaScript数组高阶函数之filter、map与reduce详解

 更新时间:2026年01月13日 10:21:43   作者:Sunny.221  
高阶函数可以帮助你增强你的JavaScript,让你的代码更具有声明性,简单来说,就是简单,简练,可读,这篇文章主要介绍了JavaScript数组高阶函数之filter、map与reduce的相关资料,需要的朋友可以参考下

1. 函数式编程简介

在JavaScript编程中,数组迭代是一项基础而重要的任务。随着函数式编程范式的普及,JavaScript提供了一系列强大的数组高阶函数,其中map、filter和reduce是最为核心和常用的三个方法。与传统的命令式编程(如for循环)相比,这些高阶函数采用声明式编程风格,使代码更加简洁、可读和易于维护。

函数式编程的核心思想是将函数作为第一公民,即函数可以像其他数据类型一样被传递、赋值和返回。这种编程范式与面向对象编程形成鲜明对比,它更注重数据的转换而非状态的改变。在JavaScript中,数组高阶函数正是这种思想的完美体现。

函数式编程是一种以函数为第一公民的编程范式,与命令式编程和面向对象编程形成对比。在 JavaScript 中,数组的高阶函数 filter、map 和 reduce 是函数式编程的典型代表,它们可

以使代码更加简洁、易读和可维护。

2. JavaScript数组迭代基础

在深入探讨高阶函数之前,我们先简要回顾JavaScript中数组迭代的基础方法。

2.1 传统迭代方法

for循环是最基础的迭代方法,通过索引访问数组的每个元素:

let array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
  console.log(array[i]); // 输出数组中的每个元素
}

forEach方法是ES5引入的更简洁的遍历方式:

let array = [1, 2, 3, 4, 5];
array.forEach(function(item) {
  console.log(item); // 输出数组中的每个元素
});

for...of循环是ES6引入的语法,直接迭代数组的元素:

let array = [1, 2, 3, 4, 5];
for (let item of array) {
  console.log(item); // 输出数组中的每个元素
}

虽然这些方法都能实现数组迭代,但它们各有优缺点。for循环灵活但代码冗长;forEach简洁但无法中断遍历;for...of语法简洁但兼容性需要考虑。

2.2 高阶函数的优势

与上述方法相比,map、filter和reduce等高阶函数具有以下显著优势:

  1. 声明式编程:关注"做什么"而非"怎么做",代码更易理解

  2. 不可变性:不会修改原数组,而是返回新数组,符合函数式编程原则

  3. 链式调用:可以轻松组合多个操作,形成清晰的数据处理管道

  4. 代码复用:将通用逻辑抽象为函数,提高代码的可维护性

3. filter 函数:数组过滤

基本概念

filter 函数用于创建一个新数组,包含通过指定函数测试的所有元素。它不会改变原始数组,而是返回一个新的过滤后的数组。

语法结构

let newArray = arr.filter(function(currentValue[, index[, array]]) {
  // 返回 true 保留元素,false 过滤元素
}[, thisArg])

核心特性

  • 过滤机制:根据回调函数返回的布尔值决定是否保留元素(true保留,false过滤)

  • 应用场景:从数组中筛选出满足特定条件的元素

使用示例

const nums = [10, 20, 111, 222, 444, 40, 50]
let newNums = nums.filter(function(n) {
  return n < 100
})
// 结果: [10, 20, 40, 50]

箭头函数简化

let newNums = nums.filter(n => n < 100)

4. map 函数:数组映射

基本概念

map 函数创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后的返回值。它不会改变原数组,而是返回一个新数组。

语法结构

let newArray = arr.map(function(currentValue[, index[, array]]) {
  // 返回新元素值
}[, thisArg])

核心特性

  • 映射转换:对数组中的每个元素应用转换函数,生成新数组

  • 应用场景:将数组元素从一种形式转换为另一种形式

使用示例

let new2Nums = newNums.map(function(n) {
  return n * 2
})
// 结果: [20, 40, 80, 100]

箭头函数简化

let new2Nums = newNums.map(n => n * 2)

5. reduce 函数:数组汇总

基本概念

reduce 函数对数组中的每个元素执行一个由您提供的 reducer 函数,将其结果汇总为单个返回值。它是处理数组汇总操作的强大工具。

语法结构

let result = arr.reduce(function(accumulator, currentValue[, index[, array]]) {
  // 返回新的累加器值
}[, initialValue])

核心特性

  • 汇总聚合:将数组中的所有元素通过回调函数累加为一个最终值

  • 参数说明

    • accumulator:累加器,保存上一次回调的返回值

    • currentValue:当前正在处理的元素

    • initialValue(可选):作为第一次调用回调函数的初始值

使用示例

let total = new2Nums.reduce(function(preValue, n) {
  return preValue + n
}, 0)
// 结果: 240

箭头函数简化

let total = new2Nums.reduce((pre, n) => pre + n, 0)

6. 链式调用:组合使用

这三个方法的真正威力在于可以将它们链式调用,创建出高效且表达性强的数据处理流程。

链式调用的开销:每个方法都会生成新数组,处理大规模数据时可能影响性能。此时可考虑使用 for循环合并操作。

完整示例

// 分开调用
let total = nums.filter(n => n < 100)
               .map(n => n * 2)
               .reduce((pre, n) => pre + n, 0)

// 单行简洁写法
let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n)

复杂数据处理示例

// 处理对象数组的复杂案例
let users = [
  { name: 'Alice', age: 22 },
  { name: 'Bob', age: 17 },
  { name: 'Charlie', age: 30 }
]

let totalAge = users.filter(user => user.age > 18)
                   .map(user => user.age)
                   .reduce((sum, age) => sum + age, 0)
// 结果: 52

7. 三种方法对比总结

方法

返回类型

是否修改原数组

主要用途

filter

新数组

过滤数组中符合条件的元素

map

新数组

转换数组中的每个元素

reduce

任意类型(单个值)

将数组聚合为一个值

8. 性能考虑与优化建议

虽然这些高阶函数提供了声明式和简洁的数组处理方式,但在处理大型数据集时,它们的性能可能不如传统的 for 循环。这是因为高阶函数在内部会进行循环迭代,但额外的函数调用和上下文切换可能会引入额外开销。

优化建议

  • 避免不必要的链式调用,尽量在一个迭代中完成多个操作

  • 处理大型数据集时,考虑使用传统的 for 循环

  • 链式调用时,先使用 filter 方法减少数据集,再进行 map 和 reduce 操作

9. 实际应用场景

数据处理管道

let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

let result = data.filter(num => num % 2 === 0)    // 筛选偶数
                 .map(num => num * 2)            // 乘以2
                 .filter(num => num > 5)          // 筛选大于5的数
                 .reduce((sum, num) => sum + num, 0) // 求和
// 结果: 24

数组去重

let arr = [1, 2, 2, 3, 4, 4, 5]
let uniqueArr = arr.filter((value, index, self) => {
  return self.indexOf(value) === index
})
// 结果: [1, 2, 3, 4, 5]

这些数组高阶函数是现代 JavaScript 开发中的重要工具,掌握它们能够帮助你写出更简洁、优雅和可维护的代码。

到此这篇关于JavaScript数组高阶函数之filter、map与reduce详解的文章就介绍到这了,更多相关JS数组高阶函数filter、map与reduce内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • BootStrap与Select2使用小结

    BootStrap与Select2使用小结

    这个select2组件的功能确实很强大,可以将图片放入到select里面随着文字一起显示。接下来通过本文给大家分享BootStrap与Select2使用小结,需要的朋友参考下
    2017-02-02
  • 将字符串转换成gb2312或者utf-8编码的参数(js版)

    将字符串转换成gb2312或者utf-8编码的参数(js版)

    直接在url中传递中文参数时,读到的中文都是乱码,那么我们应该怎么将这些参数转换呢,接下来与大家分享下将字符串转换成utf-8或者gb2312编码的参数的技巧
    2013-04-04
  • 鼠标滚轮控制网页横向移动实现思路

    鼠标滚轮控制网页横向移动实现思路

    设置window的scrollLeft值,这里一定要是window不能是body否则滚动有问题,绑定事件mousewhell 也必须是在body上,感兴趣的各位可以了解下哈,希望可以帮助到你
    2013-03-03
  • Javascript动画效果(2)

    Javascript动画效果(2)

    这篇文章主要为大家详细介绍了第二篇Javascript动画效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • fetch 如何实现请求数据

    fetch 如何实现请求数据

    这篇文章主要介绍了fetch 如何实现请求数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-12-12
  • js同源策略详解

    js同源策略详解

    这篇文章主要介绍了js同源策略,较为详细的分析了javascript中同源策略的概念与相关应用注意事项,需要的朋友可以参考下
    2015-05-05
  • 一文详细分析npm、pnpm、yarn的区别

    一文详细分析npm、pnpm、yarn的区别

    npm,yarn,pnpm都是前端常用的包管理工具,那它们3者之间又有什么区别呢,这篇文章主要介绍了npm、pnpm、yarn区别的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-12-12
  • JS简单循环遍历json数组的方法

    JS简单循环遍历json数组的方法

    这篇文章主要介绍了JS简单循环遍历json数组的方法,结合实例形式简单分析了JavaScript循环遍历json数组的方法,并提供了jQuery遍历json的方法,需要的朋友可以参考下
    2016-04-04
  • js arguments,jcallee caller用法总结

    js arguments,jcallee caller用法总结

    这篇文章主要介绍了js中arguments, jcallee caller用法。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-11-11
  • 前端CryptoJS加密、后端JAVA解密代码实现参考

    前端CryptoJS加密、后端JAVA解密代码实现参考

    这篇文章主要介绍了前端CryptoJS加密、后端JAVA解密代码实现参考,需要的朋友可以参考下
    2023-12-12

最新评论