欢迎光临北京市聚强科技
详情描述
JavaScript 数组高阶函数详解:filter、map 与 reduce

概述

JavaScript 的数组高阶函数是函数式编程的核心工具,它们接收函数作为参数,使代码更简洁、可读且易于维护。其中最常用的三个是 filtermapreduce

1. filter() - 过滤数组

基本语法

const newArray = array.filter(callback(element, index, array));

核心特性

  • 返回一个新数组,包含所有通过测试的元素
  • 不会修改原数组
  • 当测试函数返回 true 时保留元素,false时过滤掉

示例

const numbers = [1, 2, 3, 4, 5, 6];

// 过滤出偶数
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4, 6]

// 过滤出大于3的数
const greaterThanThree = numbers.filter(num => num > 3);
console.log(greaterThanThree); // [4, 5, 6]

实际应用

const users = [
  { id: 1, name: 'Alice', age: 25, active: true },
  { id: 2, name: 'Bob', age: 30, active: false },
  { id: 3, name: 'Charlie', age: 35, active: true },
  { id: 4, name: 'David', age: 20, active: false }
];

// 过滤活跃用户
const activeUsers = users.filter(user => user.active);
console.log(activeUsers); // Alice 和 Charlie

// 过滤年龄大于25的用户
const olderUsers = users.filter(user => user.age > 25);
console.log(olderUsers); // Bob 和 Charlie

2. map() - 映射/转换数组

基本语法

const newArray = array.map(callback(element, index, array));

核心特性

  • 返回一个新数组,长度与原数组相同
  • 不会修改原数组
  • 对每个元素应用转换函数

示例

const numbers = [1, 2, 3, 4];

// 将每个数字加倍
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8]

// 将数字转换为字符串
const strings = numbers.map(num => `数字: ${num}`);
console.log(strings); // ["数字: 1", "数字: 2", "数字: 3", "数字: 4"]

实际应用

const products = [
  { id: 1, name: 'Laptop', price: 999, tax: 0.1 },
  { id: 2, name: 'Mouse', price: 25, tax: 0.08 },
  { id: 3, name: 'Keyboard', price: 75, tax: 0.08 }
];

// 提取产品名称数组
const productNames = products.map(product => product.name);
console.log(productNames); // ["Laptop", "Mouse", "Keyboard"]

// 计算含税价格
const pricesWithTax = products.map(product => ({
  name: product.name,
  totalPrice: product.price * (1 + product.tax)
}));
console.log(pricesWithTax);
// [
//   { name: 'Laptop', totalPrice: 1098.9 },
//   { name: 'Mouse', totalPrice: 27 },
//   { name: 'Keyboard', totalPrice: 81 }
// ]

3. reduce() - 累积/聚合数组

基本语法

const result = array.reduce(callback(accumulator, currentValue, index, array), initialValue);

核心特性

  • 将数组缩减为单个值
  • 需要初始值(可选的,但建议提供)
  • 接收累计器和当前值作为参数

示例

const numbers = [1, 2, 3, 4, 5];

// 求和
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 15

// 求乘积
const product = numbers.reduce((acc, curr) => acc * curr, 1);
console.log(product); // 120

// 找出最大值
const max = numbers.reduce((acc, curr) => Math.max(acc, curr), -Infinity);
console.log(max); // 5

实际应用

const orders = [
  { id: 1, product: 'Apple', quantity: 2, price: 1.5 },
  { id: 2, product: 'Banana', quantity: 3, price: 0.5 },
  { id: 3, product: 'Orange', quantity: 1, price: 2.0 }
];

// 计算总销售额
const totalSales = orders.reduce((total, order) => {
  return total + (order.quantity * order.price);
}, 0);
console.log(totalSales); // (2*1.5 + 3*0.5 + 1*2.0) = 6.5

// 按产品分组统计
const productSummary = orders.reduce((summary, order) => {
  if (!summary[order.product]) {
    summary[order.product] = 0;
  }
  summary[order.product] += order.quantity;
  return summary;
}, {});
console.log(productSummary); // { Apple: 2, Banana: 3, Orange: 1 }

组合使用示例

示例1:数据处理管道

const employees = [
  { name: 'Alice', department: 'IT', salary: 60000, years: 3 },
  { name: 'Bob', department: 'HR', salary: 45000, years: 5 },
  { name: 'Charlie', department: 'IT', salary: 75000, years: 7 },
  { name: 'David', department: 'Marketing', salary: 50000, years: 2 },
  { name: 'Eve', department: 'IT', salary: 80000, years: 10 }
];

// 计算IT部门平均工资
const itAverageSalary = employees
  .filter(emp => emp.department === 'IT')      // 1. 过滤IT部门
  .map(emp => emp.salary)                      // 2. 提取工资
  .reduce((sum, salary, index, array) => {     // 3. 计算平均值
    sum += salary;
    if (index === array.length - 1) {
      return sum / array.length;
    }
    return sum;
  }, 0);

console.log(itAverageSalary); // (60000 + 75000 + 80000) / 3 = 71666.67

示例2:复杂数据转换

const data = [
  { id: 1, value: 10, category: 'A' },
  { id: 2, value: 25, category: 'B' },
  { id: 3, value: 15, category: 'A' },
  { id: 4, value: 30, category: 'C' },
  { id: 5, value: 20, category: 'B' }
];

// 按类别分组并计算每类的总和
const result = data
  .filter(item => item.value > 15)           // 过滤值大于15的项
  .reduce((groups, item) => {
    if (!groups[item.category]) {
      groups[item.category] = [];
    }
    groups[item.category].push(item);
    return groups;
  }, {});

// 进一步处理分组结果
const finalResult = Object.keys(result).map(category => ({
  category,
  count: result[category].length,
  total: result[category].reduce((sum, item) => sum + item.value, 0)
}));

console.log(finalResult);
// [
//   { category: 'B', count: 2, total: 45 },
//   { category: 'C', count: 1, total: 30 }
// ]

性能考虑与最佳实践

1. 链式调用 vs 单一循环

// 链式调用(可读性好)
const result1 = array
  .filter(x => x > 10)
  .map(x => x * 2)
  .reduce((sum, x) => sum + x, 0);

// 单一循环(性能更好)
const result2 = array.reduce((sum, x) => {
  if (x > 10) {
    return sum + (x * 2);
  }
  return sum;
}, 0);

2. 提前过滤

// 推荐:先过滤再映射
const validItems = largeArray
  .filter(item => item.isValid)    // 先过滤掉无效项
  .map(item => item.value);        // 再处理有效项

// 不推荐:先映射再过滤
const notRecommended = largeArray
  .map(item => item.value)         // 可能计算了无效项
  .filter(value => value !== null);

对比表格

特性 filter map reduce
返回值 新数组 新数组 单个值
数组长度 可能减少 保持不变 N/A
主要用途 过滤/选择 转换/映射 聚合/累积
是否改变原数组
回调函数返回值 Boolean 任意类型 累积值

总结

filter:用于从数组中筛选符合条件的元素 map:用于将数组中的每个元素转换为新形式 reduce:用于将数组中的所有元素聚合成单个值

这三个函数组合使用可以解决大多数数组处理问题,使代码更加声明式、简洁且易于维护。掌握它们能显著提升 JavaScript 编程能力。

相关帖子
2026年各大平台会员自动续费机制有何新变化,消费者该如何应对?
2026年各大平台会员自动续费机制有何新变化,消费者该如何应对?
北京市房产一押二押银行贷款|房子抵押贷款正规公司,公积金贷款代办公司
北京市房产一押二押银行贷款|房子抵押贷款正规公司,公积金贷款代办公司
带孩子上路时,如何利用常见的交通标志进行生动有趣的交通安全教育?
带孩子上路时,如何利用常见的交通标志进行生动有趣的交通安全教育?
北京市车辆押证借款@汽车押车贷款,全国车牌都可以办理
北京市车辆押证借款@汽车押车贷款,全国车牌都可以办理
北京市有汽车就可以借款-车子抵押贷款代办,企业税票贷款
北京市有汽车就可以借款-车子抵押贷款代办,企业税票贷款
定州市本人车抵押借款-汽车抵押贷款公司,专注车贷-服务好-利息低
定州市本人车抵押借款-汽车抵押贷款公司,专注车贷-服务好-利息低
2026年各地困难残疾人生活补贴标准是否有新的调整,具体提高了多少?
2026年各地困难残疾人生活补贴标准是否有新的调整,具体提高了多少?
防城港市别墅抵押银行贷款|房屋抵押贷款额度,银行贷款咨询
防城港市别墅抵押银行贷款|房屋抵押贷款额度,银行贷款咨询
为什么黄金在自然界中多以单质形式存在,而不是与其他元素激烈化合?
为什么黄金在自然界中多以单质形式存在,而不是与其他元素激烈化合?
承德市办理车抵贷-车辆典当行抵押贷款,企业税贷
承德市办理车抵贷-车辆典当行抵押贷款,企业税贷
瑞安市别墅抵押银行贷款|房产抵押银行贷款,需要公司成立1年以上
瑞安市别墅抵押银行贷款|房产抵押银行贷款,需要公司成立1年以上
济南市抵押车辆绿本借款@汽车贷款当天放款,个人消费贷款
济南市抵押车辆绿本借款@汽车贷款当天放款,个人消费贷款
企业裁员通常有哪些合法的流程和规定,员工如何判断自己是否被合规对待?
企业裁员通常有哪些合法的流程和规定,员工如何判断自己是否被合规对待?
在职业生涯的中后期,从灵活就业状态成功转向企业稳定岗位有哪些可行的路径?
在职业生涯的中后期,从灵活就业状态成功转向企业稳定岗位有哪些可行的路径?
张家口市全款车押绿本贷款-汽车抵押贷款办理押证不押车,正规安全,快至当天放款
张家口市全款车押绿本贷款-汽车抵押贷款办理押证不押车,正规安全,快至当天放款
黄金的延展性究竟有多强?一克黄金究竟可以拉伸成多长的金丝?
黄金的延展性究竟有多强?一克黄金究竟可以拉伸成多长的金丝?
常德市装修贷款公司|有房就能贷款,垫资房抵贷
常德市装修贷款公司|有房就能贷款,垫资房抵贷
个人在本地进行的发明专利获得授权,在积分申报时需准备哪些材料?
个人在本地进行的发明专利获得授权,在积分申报时需准备哪些材料?
电子租房合同日益普及,其法律效力与传统纸质合同签字有何异同?
电子租房合同日益普及,其法律效力与传统纸质合同签字有何异同?