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 |
|