前言
函数是一等公民,函数可以出现在任何它想出现的地方,函数可以完成任何它想完成的功能。
我是龙哈哈,坚信每个人都可以写出好程序,相信技术,传递价值。
本篇是 Magic JavaScript
系列的第三篇,我们来一起学习一下 函数式编程(FP)
的相关知识。
函数式编程是属于声明式编程范式
,会简要描述要做什么,但不会告诉你是如何做的。比较典型的例子是 SQL查询语句
、正则表达式
、HTML标签
等。
和声明式编程相反的另外一种编程范式是命令式编程范式
,则会一步一步的告诉你具体是如何做的。
函数+编程
用数学函数的思想来解决在编程过程中遇到的问题。
函数
我们初中就学到的知识。例如:一次函数,二次函数,三角函数,指数函数,对数函数 等等。
编程
编写程序,让计算机代码运行解决问题,最终得到相应的结果。
一道数学题
求 (1+2)*3-4
的结果
来看下不同的编程范式对应的不同写法
命令式
把运算过程拆解为一行一行的命令,命令计算机执行
// 1+2
let a = 1+2;
// (1+2)*3
let b = a*3;
// (1+2)*3-4
let c = b-4;
函数式
把运算过程拆解为有不同作用的函数,通过一系列嵌套式函数来调用
// 加法函数
function add(a,b) {
return a+b;
}
// 减法函数
function substract(a,b) {
return a-b;
}
// 乘法函数
function mutiply(a,b){
return a*b;
}
// 嵌套式函数调用
substract(mutiply(add(1,2),3),4);
特性
纯函数
就是数学里的函数。
- 相同的输入,得到相同的输出
- 无副作用
Code
// 不纯函数,运行多次,返回结果不一样,改变了外部变量counter的值
let counter = 0;
const increace = () => ++counter
increace(); // 1
increace(); // 2
// 纯函数 运行多次,输入参数一致时,返回相同结果
let newCounter = 0;
const pureIncreace(value) => value + 1;
pureIncreace(newCounter); // 1
pureIncreace(newCounter); // 1
副作用
任何与函数外部世界的交互都是副作用
- 获取/改变外部变量的值
- 打印日志
- 抛出异常
- 数据库操作
- 文件操作 副作用会让程序变得更加不确定性,副作用虽然不可能完全禁止,但可以尽可能控制它们在可控范围内发生。
柯里化
使用一部分参数调用一个函数,返回一个接受剩余参数的新函数。
Code
const add = x => y => x + y;
const add10 = add(10);
add10(90); // 100
const isGreater = x => y => y > x;
const isGreater100 = isGreater(100);
isGreater100(200) // true
Curry Function
// 柯里化实现
const curry = (fn) => {
const fnArgsLength = fn.length;
return curryFn(...args) => {
if (args.length < fnArgsLength) {
return curryFn.bind(null, ...args);
}
return fn.call(null, ...args);
}
}
// 柯里化 纯函数 match
const regMatch = curry((reg,str)=>str.match(reg));
regMatch(/o/g,'lol'); // ['o']
// 判断有没有字母O
const hasLetterO = regMatch('/o/g');
hasLetterO('lol'); // ['o']
hasLetterO('lll'); // null
柯里化是一种预加载函数
的方法,可以对参数进行缓存
,基于这种有趣的设计,会有各种各样的花式玩法。
组合函数
像堆积木一样的来组合函数式的代码组合起来调用
const composeFn = (m,n) => x => m(n(x));
再来看看数学题 (1+2)*3-4,如何使用组合式函数
const add1 = x => x+1;
const mutiply3 = x => x*3;
const substract4 = x => x-4;
// 嵌套函数
substract4(mutiply3(add1(2)));
// 组合函数
const fn = composeFn(substract4, composeFn(mutiply3,add1));
fn(2);
前端工程师日常开发工作,更多的是面向UI编程
,这种场景下,使用组合式函数
再合适不过了。
最后
我坚信每个人都可以写出好程序,相信技术,传递价值。
相信自己会越来越好,继续加油。
文中如有错误,欢迎在评论区指正。
如果这篇文章对你有所帮助,欢迎点赞、评论和关注。
系列文章
- 【Magic JavaScript】数据类型,你真的掌握了吗?
- 【Magic JavaScript】原型编程,你真的理解了吗?
- 【Magic JavaScript】函数编程,你真的会用了吗?
- 【Magic JavaScript】异步编程,你真的学会了吗?
- 【Magic JavaScript】事件循环,你真的明白了吗?
- 【Magic JavaScript】垃圾回收,你真的清楚了吗?