函数式编程

1. 什么是函数式编程

函数式编程是一种**"编程范式"**(programming paradigm),一种编写程序的方法论。

主要编程范式有三种:

  • 命令式编程(imperative)
  • 声明式编程(declarative)
  • 函数式编程(functional)

相比命令式编程,函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进、逐层推导复杂运算,而非设计一个复杂的执行过程。

// 命令式
const array = [0, 1, 2, 3];
for (let i = 0; i < array.length; i++) {
  array[i] = Math.pow(array[i], 2);
}

// 函数式
[0, 1, 2, 3].map(num => Math.pow(num, 2));

简单来讲,就是把过程逻辑写成函数,定义好输入参数,只关心它的输出结果——是一种描述集合与集合之间的转换关系,输入通过函数都会返回有且只有一个输出值。

函数实际上是一个关系/映射,这种映射关系是可以组合的:一旦一个函数的输出类型可以匹配另一个函数的输入,就能进行组合。

2. 核心概念

高阶函数(Higher-Order Function)

以函数作为输入或者输出的函数。利用高阶函数抽象"如何做"的逻辑,直接关注"做了什么"。

高阶函数存在缓存特性,主要利用闭包:

const once = (fn) => {
  let done = false;
  return function () {
    if (!done) {
      fn.apply(this, fn);
    } else {
      console.log('该函数已经执行');
    }
    done = true;
  };
};

柯里化(Currying)

把一个多参数函数转化为一个嵌套的一元函数的过程。

// 柯里化工具函数
const curry = (fn) => {
  return function curried(...args) {
    if (args.length >= fn.length) return fn(...args);
    return (...rest) => curried(...args, ...rest);
  };
};

const add = (a, b, c) => a + b + c;
curry(add)(1)(2)(3); // 6

柯里化的意义:

  • 参数复用(如固定前置参数)。
  • 延迟执行。
  • 逻辑复用(基于不同参数组合产生不同函数)。

组合(compose)与管道(pipe)

组合函数的目的是将多个函数组合成一个函数,与管道一起可以把很多小函数组合完成更复杂的逻辑。

// 从右到左执行
const compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);
// 从左到右执行
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);

const f = compose(x => x + 1, x => x * 2);
f(3); // 7

3. 优缺点

优点:

  • 代码简洁、可读性强。
  • 易于并行 / 缓存(纯函数结果可记忆化)。
  • 易于测试(确定性输入输出)。

缺点:

  • 性能可能不如命令式(中间数组、闭包开销)。
  • 递归过深可能栈溢出。
  • 学习曲线较陡。

来源整理自:我的有道云笔记