编程范式

函数式编程入门

通过学习函数式编程的基本概念,掌握纯函数、副作用、高阶函数、函数组合与函数柯里化,提升前端代码的组织能力。

🎯 引言

通过本篇文章的学习,你将理解函数式编程的核心思想,掌握如何写出结构清晰、易维护的代码。尤其是理解“函数作为一等公民”的意义,学会写纯函数,避免副作用,运用高阶函数处理数据,以及函数组合和柯里化技巧,帮助你提升代码的可复用性和可读性。


🌀 什么是函数式编程?

函数式编程(Functional Programming)是一种以函数为核心的编程范式。它强调用函数来描述程序的逻辑,而不是通过改变状态和数据。简单来说,就是把程序看成一系列函数的组合,每个函数接受输入并返回输出,而不是去修改外部的变量。

为什么要用函数式编程呢?

很多刚开始写代码的朋友,可能会写一大堆命令式的代码,变量满天飞,状态变化难以追踪。函数式编程的优势是让代码更清晰,状态更可控,减少BUG,也更容易测试和复用。


🔍 理解“函数作为一等公民”

在 JavaScript 里,函数是“一等公民”意味着:

  • 函数可以当做变量存储
  • 函数可以作为参数传递给另一个函数
  • 函数可以作为另一个函数的返回值

举个简单的例子:

function greet(name) {
    return 'Hello ' + name;
}

function sayHello(f) {
    return f('小明');
}

var message = sayHello(greet);
console.log(message); // Hello 小明

这里 greet 函数被当做参数传给了 sayHello,这就是函数作为一等公民的体现。


💡 什么是纯函数?

纯函数指的是:

  • 给定相同的输入,必定返回相同的输出
  • 不产生任何副作用(不修改外部变量、不做网络请求、不操作 DOM 等)

举个例子,下面这个函数是纯函数:

function add(a, b) {
    return a + b;
}

只要输入是 12,它总是返回 3,且不会影响外部环境。

而下面这个函数就不是纯函数,因为它会修改外部变量:

var count = 0;

function increase() {
    count = count + 1;
    return count;
}

⚠️ 什么是副作用?为什么要避免它?

副作用是指函数在运行过程中,除了返回结果以外,还对外部状态造成了影响,如修改全局变量、改变函数参数、操作 DOM、发起网络请求等。

副作用带来什么问题?

  • 程序难以预测和调试,因为函数结果依赖外部状态
  • 难以进行单元测试
  • 代码的复用性差

所以,函数式编程鼓励我们写纯函数,尽量避免副作用,保持函数的独立性和纯净性。

当确实需要副作用时,尽可能将它们隔离到程序的边缘部分,核心逻辑使用纯函数。

🎯 高阶函数的概念

高阶函数是指满足下面两个条件之一的函数:

  • 接受一个或多个函数作为参数
  • 返回一个函数作为结果

这种设计让函数变得非常灵活。

举例说明:

JavaScript 内置的 mapfilterreduce 都是高阶函数。

假设有个数组,我们要将每个数字加倍:

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

var doubled = numbers.map(function (item) {
    return item * 2;
});

console.log(doubled); // [2, 4, 6, 8]

这里 map 函数接受了一个函数作为参数。

再看一个返回函数的例子:

function makeAdder(x) {
    return function (y) {
        return x + y;
    };
}

var add5 = makeAdder(5);
console.log(add5(3)); // 8

makeAdder 是高阶函数,它返回了一个新函数,实现了加法的“定制”。


🔗 简单的函数组合

函数组合就是把多个函数连接起来,让它们依次执行,后一个函数的输入是前一个函数的输出。我们这里不用 pipe,用最简单的嵌套形式来讲。

假设有两个函数:

function double(n) {
    return n * 2;
}

function square(n) {
    return n * n;
}

如果我们想先对一个数平方,再对结果翻倍,可以写成:

var result = double(square(3));
console.log(result); // 18

这里的执行顺序是从内到外,先计算 square(3),得到 9,然后 double(9),得到 18

函数组合的好处就是代码结构清晰,逻辑分明,每个函数只做一件事。


🌀 什么是函数柯里化?

函数柯里化(Currying)是把一个多参数函数,拆分成多个单参数函数,并且返回新的函数。通过柯里化,我们可以实现部分应用参数的效果。

举个例子:

function add(x) {
    return function (y) {
        return x + y;
    };
}

var add10 = add(10);
console.log(add10(5)); // 15

这里 add 函数接收一个参数 x,返回一个新函数,再接收参数 y,最后返回两者相加。

柯里化的好处在于,我们可以创建定制化的函数,比如上面 add10 就是一个加10的函数。


🧾 小节总结

  • 函数作为一等公民 让函数可以自由传递和返回,增强代码灵活性。
  • 纯函数 不依赖外部状态,避免副作用,代码更安全易维护。
  • 高阶函数 接收或返回函数,解耦逻辑,实现代码复用。
  • 函数组合 将小函数连接起来,形成复杂逻辑,保持清晰结构。
  • 函数柯里化 通过拆分参数,实现函数的部分应用和定制。

❓ 知识问答(Q&A)

Q:什么是纯函数,举个例子。
A:纯函数是相同输入总有相同输出且无副作用的函数。比如 function add(a, b) { return a + b; } 就是纯函数。

Q:为什么要避免副作用?
A:副作用会让程序状态复杂难控,增加调试难度,降低代码复用性和测试方便度。

Q:什么是高阶函数?
A:高阶函数是接受函数作为参数或返回函数的函数,比如 mapfilter

Q:函数柯里化有什么用?
A:柯里化方便创建定制化函数,实现函数复用和灵活调用。


🧪 小练习

练习 1:写一个纯函数 multiply,接受两个数字参数,返回它们的乘积。

function multiply(a, b) {
    // 在这里补充代码
}

练习 2:写一个高阶函数 repeat,接受一个函数和次数,返回新的函数,调用时会重复执行传入的函数指定次数。

function repeat(fn, times) {
    // 在这里补充代码
}

🎉 恭喜你已经掌握函数作为一等公民、纯函数、高阶函数、函数组合、函数柯里化技能啦! 希望你能用函数式编程让代码变得更整洁、高效、可维护。