5.纯函数
2021-09-16 本文已影响0人
静昕妈妈芦培培
理解JavaScript纯函数
函数式编程中有一个非常重要的概念叫纯函数,JavaScript符合函数式编程的范式,所以也有纯函数的概念;
- 在react开发中纯函数是被多次提及的;
- 比如react中组件就被要求像是一个纯函数(为什么是像,因为还有class组件),redux中有一个reducer的概念,也是要求必须是一个纯函数;
- 所以掌握纯函数对于理解很多框架的设计是非常有帮助的;
纯函数的维基百科定义:
在程序设计中,若一个函数符合以下条件,那么这个函数被称为纯函数:
-
此函数在相同的输入值时,需产生相同的输出
。 - 函数的输出
和输入值以外的其他隐藏信息或状态无关
,也和由I/O设备产生的外部输出无关
。 - 该函数
不能有语义上可观察的函数副作用
,诸如“触发事件”,使输出设备输出,或更改输出值以外物件的内容
等。
当然上面的定义会过于的晦涩,所以我简单总结一下:
- 确定的输入,一定会产生确定的输出;
- 函数在执行过程中,
不能产生副作用
;
副作用的理解
那么这里又有一个概念,叫做副作用,什么又是副作用呢?
- 副作用(side effect)其实本身是医学的一个概念,比如我们经常说吃什么药本来是为了治病,可能会产生一些其他的副作用;
- 在计算机科学中,也引用了
副作用
的概念,表示在执行一个函数时,除了返回函数值之外,还对调用函数产生了附加的影响
,比如修改了全局变量
,修改参数
或者改变外部的存储
;
纯函数在执行的过程中就是不能产生这样的副作用:
- 副作用往往是产生bug的 “温床”
纯函数的案例
/**
* 数组的slice方法是一个纯函数
* 对于同一个数组,调用slice方法,给其传入确定的start和end,它给我们返回确定的值
* 不会修改原来数组
*/
var names = ["lily", "curry", "why", "kobe"];
var newNames = names.slice(0, 2);
console.log(newNames); //["lily", "curry"]
console.log(names); //["lily", "curry", "why", "kobe"]
/**
* 数组的splice方法不是一个纯函数
* 对于同一个数组,调用splice方法,给其传入确定的start和end,它给我们返回不确定的值
* 会修改原来数组
* splice方法会在原数组上从start位置开始截取,截取掉num个元素,改变了原数组
* splice方法会创建一个空数组,把截取的元素push到这个空数组中,然后把存储这截取元素的数组返回
*/
var names = ["lily", "curry", "why", "kobe"];
var newNames = names.splice(1, 2);
console.log(newNames); //["curry", "why"]
console.log(names); //["lily", "kobe"]
//sum是纯函数
function sum(num1, num2) {
return num1 + num2;
}
//bar不是一个纯函数,因为修改了作用域外的变量
var num = 100;
function bar() {
num++;
}
//baz不是一个纯函数,因为修改了作用域外的对象的属性
function baz(info) {
info.name = "curry";
}
var obj = { name: "lily" };
baz(obj);
//test是一个纯函数
//因为相同的输入,产生相同的输出,并且没有副作用
function test(info) {
return {
...info,
age: 100
}
}
test(obj)
纯函数的优势
为什么纯函数在函数式编程中非常重要呢?
- 因为你可以
安心的编写
和安心的使用
; - 你在写的时候保证了函数的纯度,只是单纯实现自己的业务逻辑即可,不需要关心传入的内容是如何获得的或者依赖其他的外部变量是否已经发生了修改;
- 你在用的时候,你确定你的输入内容不会被任意篡改,并且
自己确定的输入,一定会有确定的输出
;
React中就要求我们无论是函数还是class声明一个组件,这个组件都必须像纯函数一样,保护它们的props不被修改:
非常感谢王红元老师的深入JavaScript高级语法让我学习到很多 JavaScript
的知识