JavaScript 函数式编程基础
函数式编程是一种编程范式,它将计算机运算视为函数的计算。
函数式编程语言语言最重要的基础是 $\lambda$ 演算。JavaScript 是一种十分灵活的编程语言,其可以算是多范式语言,即支持函数式编程、命令式编程、对象式编程等。
函数式编程涉及许多数学概念,不同于过程式编程和对象式编程,由其名字即可看出,在函数式编程中,函数是一等公民。函数式编程涉及的概念有:
- 闭包
 - 高阶函数
 - 柯里化
 - 偏应用
 - 组合与管道
 - 函子
 - Monad
 
函数式编程定义
函数式编程是将函数作为编程的基础,并且函数总是接受参数,返回一个值,并且遵循相同的参数总是输出相同的值。函数应该依据接收到的参数运行,不依赖外部环境的运行,即函数必须是纯函数。
特性:
- 引用透明性
- 即相同的参数总是输出相同的值
 
 - 主张命令式编程、编写抽象的代码
- 利于重用代码
 
 - 纯函数
- 遵循相同的参数总是输出相同的值,且函数应该依据接收到的参数运行,不依赖外部环境的运行
 - 有利于代码测试
 
 - 可实现并发代码
 - 可缓存
 - 支持管道与组合,类似于 
linux命令的函数式组合命令 
闭包与高阶函数
高阶函数是用于抽象通用代码的问题,即高阶函数就是定于抽象函数。这种抽象不仅可以使使用者不必在意其实现细节即可使用,且便于测试代码。
例如:实现一个 forEach 遍历数组,并对每一个item执行给定的函数,用户只需给出数组和执行函数即可;注意,实现的函数与数组原生方法作用一致,但是 .forEach() 的执行方式是声明式的而不是函数式的。
1  |  | 
也可以封装一个遍历对象的函数 eachObject:
1  |  | 
一些实用的高阶函数:
every
用于检查数组内所有值都符合给定的函数返回 true
1  |  | 
some or any
与 every 函数类似,查找数组内是否有值符合给定的函数返回 true
1  |  | 
sortBy
js数组内置的sort接收一个函数作为排序的依据,这个函数是个很公式化的函数,可以使用高阶函数抽象一下。
1  |  | 
例如,有个二维数组 arr = [[1,15], [4, 6], [7, 8]],可以使用 arr.sort(sortBy(1)) 来排序。
tap
用于调试数据的函数
1  |  | 
unary
当使用类似于 ['1', '2', '3'].map(parseInt) 是,并不会返回我们所期望的值:[1,2,3],而是会返回 [1, NaN, NaN] 。原因在于 parseInt 函数可能接收2个参数,map将数组的index作为参数传递给parseInt函数了:
1  |  | 
如果需要解决以上问题,可以使用 arr.map(args => parseInt(args)) 。
我们可以抽象一个函数用于解决以上问题,判断给定的函数接受几个参数,以不同的方式调用返回:
1  |  | 
现在可以直接使用:arr.map(unary(parseInt)) 
once
在某些情况下,某些函数只需要调用一次,为了防止其多次调用,可以封装一个函数:
1  |  |