源本科技 | 码上会

JavaScript 高阶函数

2025/12/30
16
0

学习目标

  • 理解高阶函数的定义与核心特征

  • 掌握 JavaScript 中常用的数组高阶方法(mapfilterreduce 等)

  • 能够使用高阶函数实现函数组合柯里化记忆化

  • 理解高阶函数如何提升代码的可复用性模块化声明式风格

  • 在实际开发中合理运用高阶函数编写更简洁、健壮的代码


什么是高阶函数

高阶函数是指满足以下任一条件的函数:

  1. 接收一个或多个函数作为参数

  2. 返回一个函数作为结果

核心思想:函数是一等公民,可以像数字、字符串一样被传递、赋值、返回。

function greet() {
    console.log("Hello, World!");
}

function repeat(action) {
    action();
    action();
}

repeat(greet); // 输出两次 "Hello, World!"
  • repeat 是高阶函数(接收函数 action 作为参数)

  • greet 是回调函数(Callback)


高阶函数的数组方法

这些方法是函数式编程的基石,强调不可变性(不修改原数组)和声明式风格

1. map()

转换数组,详情请参考《JavaScript 高阶函数 map

对每个元素应用函数,返回新数组。

const numbers = [1, 2, 3, 4, 5];
const squares = numbers.map(num => num * num);
console.log(squares); // [1, 4, 9, 16, 25]

特点:

  • 返回新数组,长度与原数组相同

  • 原数组不变(不可变性)


2. filter()

筛选元素,详情请参考《JavaScript 高阶函数 filter

保留满足条件的元素。

const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]

特点:

  • 返回新数组,长度 ≤ 原数组

  • 条件为 true 的元素被保留


3. reduce()

归约聚合

将数组“压缩”为单个值(如求和、拼接等)。

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 15
  • acc:累加器(accumulator)

  • curr:当前元素

  • 0:初始值(可选,但建议显式提供)

应用场景:求和、求积、扁平化数组、统计计数等。


4. forEach()

执行副作用

对每个元素执行操作(如打印、DOM 操作),不返回新数组

[1, 2, 3].forEach(num => console.log(num * 2));
// 输出:2, 4, 6

注意:forEach 不能链式调用,也不支持 break/continue


5. find()

查找首个匹配项,详情请参考《JavaScript 高阶函数 find

返回第一个满足条件的元素,否则 undefined

const users = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}];
const user = users.find(u => u.id === 2);
console.log(user); // {id: 2, name: 'Bob'}

6. some()every()

逻辑判断,详情请参考《JavaScript every 与 some 的区别

方法

行为

some()

至少一个元素满足条件 → true

every()

所有元素都满足条件 → true

const nums = [1, 2, 3, -1];
console.log(nums.some(n => n < 0));  // true
console.log(nums.every(n => n > 0)); // false

高阶函数的高级技巧

1. 函数组合

将多个函数串联执行:f(g(x))

function add(x) { return x + 2; }
function mul(x) { return x * 3; }

function compose(f, g) {
    return function(x) {
        return f(g(x));
    };
}

const result = compose(add, mul)(4); // add(mul(4)) = add(12) = 14
console.log(result); // 14

优势:构建复杂逻辑时保持代码清晰、可测试、可复用。


2. 柯里化

将多参函数转为一系列单参函数,利用闭包保存中间状态。

function multiply(a) {
    return function(b) {
        return a * b;
    };
}

const double = multiply(2);
console.log(double(5)); // 10
console.log(double(7)); // 14

应用:创建专用工具函数(如 fetchUserById = fetchUser.bind(null, 'user')


3. 记忆化

缓存函数结果,避免重复计算。

function memoize(fn) {
    const cache = {};
    return function(arg) {
        if (cache[arg] !== undefined) {
            return cache[arg];
        }
        const result = fn(arg);
        cache[arg] = result;
        return result;
    };
}

function slowCompute(n) {
    console.log("Computing...");
    return n * 2;
}

const fastCompute = memoize(slowCompute);
console.log(fastCompute(5)); // Computing... 10
console.log(fastCompute(5)); // 10(直接从缓存读取)

适用场景:递归(如斐波那契)、昂贵计算、API 请求缓存。


高阶函数的应用场景

1. 作为参数传递

控制流程解耦

function greet(name, callback) {
    console.log("Hello, " + name);
    callback();
}

function sayGoodbye() {
    console.log("Goodbye!");
}

greet("Coder", sayGoodbye);
// 输出:
// Hello, Coder
// Goodbye!

优势:将“问候”与“告别”逻辑分离,提高复用性。


2. 返回函数

创建函数工厂

function createMultiplier(factor) {
    return function(num) {
        return num * factor;
    };
}

const triple = createMultiplier(3);
console.log(triple(4)); // 12
  • 利用闭包捕获 factor

  • 实现配置化函数生成


3. 数组方法

声明式数据处理

// 传统 for 循环(命令式)
const doubled = [];
for (let i = 0; i < arr.length; i++) {
    doubled.push(arr[i] * 2);
}

// 使用 map(声明式)
const doubled = arr.map(x => x * 2);

声明式优势:

  • 更易读、更少出错

  • 自动处理边界(如空数组)

  • 支持链式调用:

    arr
      .filter(x => x > 0)
      .map(x => x * 2)
      .reduce((a, b) => a + b, 0);

重点总结

特性

说明

定义

接收函数或返回函数的函数

核心价值

提升代码复用性、模块化、可测试性

常用方法

map, filter, reduce, forEach, find, some, every

高级技巧

函数组合、柯里化、记忆化

编程范式

支持函数式编程与声明式风格

注意事项

避免过度嵌套,注意性能(如 reduce 初始化值)


思考题

  1. 以下代码输出什么?为什么?

    const arr = [1, 2, 3];
    arr.forEach(x => x * 2);
    console.log(arr);
  2. 如何用 reduce 实现 mapfilter 的功能?尝试写出通用版本。