纯函数
什么是纯函数呢?就是很纯的,没有副作用的函数… …
什么是副作用呢,就是那个,吃药的时候,说明书上写明可能产生副作用的那些不正常的作用,这个就是副作用…
好多的废话,看代码吧
简单的纯函数:
// 一个简单的纯函数
function add(a, b) {
return a + b
}
// 调用
let sum = add(1, 2)
上面的函数,无论怎么调用,都不会对其他地方产生影响,且对于相同的输入,永远都有相同的输出。
这个就是纯函数。
那么不纯的函数是什么样呢,大概有以下几种:
不纯的函数:
function add(a, b) {
c = a + b
return a + b
}
// 调用
let sum = add(1, 2)
上面的函数,虽然对于相同的输入,也永远都有相同的输出,但是它有副作用,这个副作用就是c,这个c有可能把全局已经存在的c的值给改了,也可能创建了一个全局变量c,至于会产生上面影响,这个不好说。
这个产生了副作用的函数,不是纯函数。
再看下面这个:
let mini = 18
function checkAge(age) {
return age >= mini
}
上面这个函数,没有产生副作用,也似乎对于相同的输入会有相同的输出。
但是这个函数依赖一个外部变量mini,这个变量在本函数的外部,具有不确定性,一旦被其他代码更改,对于相同的输入,就不会有相同的输出了。
所以这个也不是纯函数。
所以,纯函数就像是数学中的函数,用来描述输入和输出之间的关系,y = f(x)
所以,纯函数就是:对于相同的输入,永远都会有着相同的输出,且没有任何可观察的副作用。
纯函数有什么好处呢?
- 可缓存:因为纯函数对相同的输入始终有相同的结果,所以可以把纯函数的结果缓存起来;
- 可测试:毋庸置疑,纯函数可以让测试更方便;
- 并行处理:在多线程环境下并行操作共享的内存数据很可能会出现意外情况,纯函数不需要访问共享的内存数据,所以在并行环境下可以任意运行纯函数 (Web Worker);
- 安全稳定:纯函数没有副作用,不会出现由副作用产生的难以排查的bug。
副作用让一个函数变的不纯(如上例),纯函数的根据相同的输入返回相同的输出,如果函数依赖于外部的状态就无法保证输出相同,就会带来副作用。
副作用来源:
- 配置文件
- 数据库
- 获取用户的输入
所有的外部交互都有可能带来副作用,副作用也使得方法通用性下降不适合扩展和可重用性,同时副作用会给程序中带来安全隐患给程序带来不确定性,但是副作用不可能完全禁止,尽可能控制它们在可控范围内发生。
柯里化
柯里化是啥就先不解释了,直接上车吧。
使用柯里化解决硬编码的问题:
function checkAge(age) {
let min = 18
return age >= min
}
直接写在程序内部的具体数字课称之为硬编码,在程序编写中往往不推荐硬编码,如上代码可更改为:
// 普通纯函数
function checkAge(min, age) {
return age >= min
}
checkAge(18, 24)
checkAge(18, 20)
checkAge(20, 30)
没有了硬编码,min值可手动配置,更灵活了。
但是,如果每次调用这函数所需的min值都相同呢?这就造成代码大量重复,针对这个问题,可再次修改如下:
// 柯里化
function checkAge(min) {
return function (age) {
return age >= min
}
}
// ES6 写法
let checkAge = min => (age => age >= min)
// 生成新函数
let checkAge18 = checkAge(18)
let checkAge20 = checkAge(20)
// 调用
checkAge18(24)
checkAge18(20)
好的多了,不是么,这只是一个简单示例,但这就是函数柯里化思想:
- 当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数以后永远不变);
- 然后返回一个新的函数接收剩余的参数,返回结果。
从上面代码可以看出,这种形式的函数柯里化是利用闭包特性实现的,其实用bind也可以实现函数柯里化:
// 普通纯函数
function checkAge(min, age) {
return age >= min
}
console.log(checkAge(18, 16))
console.log(checkAge(18, 23))
// 柯里化
let checkAge18 = checkAge.bind(null, 18)
console.log(checkAge18(16))
console.log(checkAge18(23))
总结:
- 柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数;
- 这是一种对函数参数的’缓存’;
- 让函数变的更灵活,让函数的粒度更小;
- 可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能。
文章内容输出来源:拉勾大前端高薪训练营,以上文章中的内容根据老师讲课的语音和代码,结合自己的理解编辑完成,请勿抄袭,转载请注明出处。