函数式编程入门
🎯 引言
通过本篇文章的学习,你将理解函数式编程的核心思想,掌握如何写出结构清晰、易维护的代码。尤其是理解“函数作为一等公民”的意义,学会写纯函数,避免副作用,运用高阶函数处理数据,以及函数组合和柯里化技巧,帮助你提升代码的可复用性和可读性。
🌀 什么是函数式编程?
函数式编程(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;
}
只要输入是 1 和 2,它总是返回 3,且不会影响外部环境。
而下面这个函数就不是纯函数,因为它会修改外部变量:
var count = 0;
function increase() {
count = count + 1;
return count;
}
⚠️ 什么是副作用?为什么要避免它?
副作用是指函数在运行过程中,除了返回结果以外,还对外部状态造成了影响,如修改全局变量、改变函数参数、操作 DOM、发起网络请求等。
副作用带来什么问题?
- 程序难以预测和调试,因为函数结果依赖外部状态
- 难以进行单元测试
- 代码的复用性差
所以,函数式编程鼓励我们写纯函数,尽量避免副作用,保持函数的独立性和纯净性。
🎯 高阶函数的概念
高阶函数是指满足下面两个条件之一的函数:
- 接受一个或多个函数作为参数
- 返回一个函数作为结果
这种设计让函数变得非常灵活。
举例说明:
JavaScript 内置的 map、filter、reduce 都是高阶函数。
假设有个数组,我们要将每个数字加倍:
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:高阶函数是接受函数作为参数或返回函数的函数,比如 map、filter。
Q:函数柯里化有什么用?
A:柯里化方便创建定制化函数,实现函数复用和灵活调用。
🧪 小练习
练习 1:写一个纯函数 multiply,接受两个数字参数,返回它们的乘积。
function multiply(a, b) {
// 在这里补充代码
}
练习 2:写一个高阶函数 repeat,接受一个函数和次数,返回新的函数,调用时会重复执行传入的函数指定次数。
function repeat(fn, times) {
// 在这里补充代码
}
🎉 恭喜你已经掌握函数作为一等公民、纯函数、高阶函数、函数组合、函数柯里化技能啦! 希望你能用函数式编程让代码变得更整洁、高效、可维护。
