特点
- 声明式编程,关注每一步的输入输出
- 若干纯函数的组合,集中处理的副作用
想要了解整体代码逻辑,只需去阅读函数组合在语意上做了什么事情
纯函数特点
幂等性
- 引用透明,函数调用能被函数输出值直接替代
- 结果可预测
-
纯函数组合需要满足的条件
组合指的是代码以明确,明显和可读的方式描述数据流,如果函数类型 (shape) 相匹配,函数就能比较容易组合起来
函数类型由输入输出值的个数决定 一元函数(unary function):单输入,单输出
- 二元函数(binary function):两个输入,单个输出
函数具备相同的类型时是可互换的(interchangeable)
保证函数类型一致的方法(改变函数参数个数)
偏函数
function partial(fn,...presetArgs) {return function partiallyApplied(...laterArgs){return fn( ...presetArgs, ...laterArgs );};}
柯理化
function curry(fn,arity = fn.length) {return (function nextCurried(prevArgs) {return function curried(nextArg) {var args = [ ...prevArgs, nextArg ];if (args.length >= arity) {return fn( ...args );}else {return nextCurried( args );}};})( [] );}
常用组合及典型例子
compose函数
将一个函数的输出立即传入另外一个函数当作输入
函数从右向左执行;
pipe函数
函数从左向右执行;
function compose(...args) {
return pipe(...fns.reverse())
}
function pipe(...fns) {
return function piped(v){
for(let fn of fns){
v = fn(v)
}
return v
}}
递归函数(recursion)
- 基线条件(base case):函数不再调用自己的条件
- 递归条件(recursive case): 函数调用自己的条件
- 易懂消耗内存
内存优化方案
- tail calls,可能大家听说最多的递归优化方案就是尾调用,不过尾调用需要系统,语言,编译器,运行环境等等都支持才行,目前只有 Safari 浏览器支持,需要在 strict 模式,且递归直接返回函数时才生效;
- CPS:一种欺骗性的突破栈内存限制的方法;
-
reducer
transduction
monad
其他
参数的表示
parameters 的个数可以通过
fn.length获取,其在定义时决定arguments.length属性则在运行时决定函数名很重要:
函数名能出现在调用栈中,排查bug
在需要自引用的地方,函数名必不可少,比如递归或者事件处理函数副作用
I/O (console,files,etc)
- Database Storage
- Network Calls
- DOM
- TimeStamps
- Random Numbers
- CPU Heat
- CPU Time Delay:对系统有影响
