如果理解直接看为一等公民的好处好处。
其实说函数式一等公民的意思就是说函数和其他“公民”具有相同的属性。就像任何一种数据类型,它能够被存储在数组中,能够作为函数的参数,能够赋值给变量:
上面的代码没有什么意义,只是表达函数在JavaScript中是一等公民,和一个值一样。
拿一个callback的例子来讲,比如你用fetch发个请求时:
上面其实可以直接传递一个函数作为回调,加一层包裹其实没有必要:
多一层函数的包裹并没有任何意义,完全是多余的代码。再看一个例子:
上面的代码其实就是聚合一些功能作为一个对象,但是多加了一层的函数,也是没有必要的,在阅读的时候到会增加复杂度,其实postController.find === Db.find
,所以完全没有再去包裹一层函数:
上面的代码是不是更表意,然而如果js的函数不能像值一样传递,上面的简写都是不可能的。上面的代码其实还有一个好处,你不用去纠结如何命名在两层函数之间的参数了。这种风格代码是符合Pointfree的,我们后面要介绍。另外,函数式编程是操作函数的,所以函数是一等公民也是函数式的基石,基本上如果js不支持这一项,函数式根本玩不转。
让我举一个例子,大家在小学多学过一元一次方程吧:
这就是一个纯函数,一个输入然后返回一个输出。所有的东西都是围绕输入的,一个输入只可能返回一个输出,然后对任何其他没在作用域中的变量没有任何操作。
更书面的解释:一个纯函数一个输入永远都只有一个同样的输出,然后不会产生任何副作用。副作用是啥我们一会儿再说。
通常不纯的函数分为两类,一种是会改变输入的:
上面中在numbers这个数组上面的两个方法,slice
是纯函数。而splice则不是纯函数,它会改变输入的数值。做了额外的事。
另外一种是对函数以外的状态有依赖的:
像上面的函数,第一个就是不纯的,他依赖的作用域之外的一个变量,一旦这个变量改变,这个函数返回的值就会跟着改变。
副作用就是在函数计算过程中,对函数外的状态进行更改或则与函数外状态进行交互的行为。首先副作用会导致函数不纯,是程序有不可控的依赖,不便于管理。但是,副作用是不可消除的,在正常的编程活动中是必然伴随着副作用的。所以在面对副作用时,问题不是如何消除副作用,而是如何管理副作用。这个,会在我们讲解范畴论相关概念的时候再深入。
正常编程活动中会引入的副作用有这些:
当然不限于上面这几种,还有很多行为都带有副作用。
纯函数的每次输入和输出都是没有状态的,所以结果都一样,能够被缓存在任何地方而不会造成错误。
第二个signUp
依赖是从上传递的,所以能直观的看出saveUser
需要Db
,welcomeUser
还需要Email
。在不纯的函数中你很难在调用的时候知道他的依赖,你需要查看代码,才能搞清楚,“哦,原来还用了Db存了波数据啊。”
依赖作为参数传入,也很容易的在移植到其他场景使用,毕竟函数只是功能,针对不同场景操作不同的数据。
写单测的时候,最麻烦的就是如何mock数据。通常有两类数据最难mock,第一个是全局变量,比如document
,另外一类是import
进来的依赖,对于这两种,虽然在一些测试套件中有现成的工具库去mock。但是,都是很诡异的方式。
而如果是函数式的话,你测的就是一个输入一个输出,没有外部的影响,是非常容易测试的。
纯函数都是没有状态的,那即使跑在多台机器多个进程,每个单元相互之间是没有耦合关系的。
大家可以看阮老师的这篇博客了解一下:http://www.ruanyifeng.com/blo...
我只扯一下Pointfree风格代码的好处:
当然也有人认为其将太多的状态隐藏了,初读代码很难理解,只有看了具体函数实现功能才能知道真正的意图,对于代码的可读性而言,很糟糕。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。