一、什么是函数式编程
函数式编程(Functional Programming, FP),是一种编程风格,也可以认为是一种思维模式,和面向过程、面向对象是并列的关系。 函数式编程是对运算过程的抽象,函数指的并不是程序中的函数或者方法,而是数学中的函数映射关系,例如:y=cos(x),是y和x的关系。 在函数式编程中,相同的输入时必须得到相同的输出,也称为纯函数。 在函数式编程中,我们会将函数抽象为细粒度的函数,将这些函数组合为功能更强大的函数。
// 非函数式编程
let num1 = 2
let num2 = 3
let sum = num1 + num2
console.log(sum)
// 函数式编程
function add(n1, n2) {
return n1 + n2
}
let sum = add(2, 3)
console.log(sum)
函数式编程不依赖、不改变外界的状态,相同的输入必定返回相同的输出。因此,每个函数都是独立的,利于进行单元你测试和排错,以及函数的复用组合。
二、函数式编程基础
- 函数是一等公民;
- 高阶函数
- 闭包
- 纯函数
函数是一等公民
在JavaScript中”万物皆对象“,因此函数在JS中也是一个对象,我们可以把函数存储到变量或者数组中,函数也可以作为别的函数的参数和返回值。
一等公民的特性:
- 函数可以存储在变量或者数组中
- 函数可以作为参数传递
- 函数作为返回值
//把函数复制给变量
let sayHi = function () {
console.log("hi")
}
// 函数作为参数
function forEach (array,fn) {
for(let item of array) {
fn(item)
}
}
// 测试
let arr = [1,2,3]
let func = function (value) {
value = value * 2
console.log(value)
}
forEach(arr,func) // 2 4 6
// 函数作为返回值
function sayHi () {
let msg = 'hi'
return function () {
console.log(msg)
}
}
// 使用
const hi = sayHi() //返回的是函数function () {console.log(msg)}
//因此可以有两种调用方式
hi() // hi
sayHi()()//hi
高阶函数
什么是高阶函数:
- 函数作为参数;
- 函数作为返回值
例如:forEach fliter等函数
闭包
当通过调用外部函数返回的内部函数后,即使外部函数已经执行结束了,但是被内部函数引用的外部函数的变量依然会保存在内存中,我们把引用了其他函数作用域变量的函数和这些被引用变量的集合,称为闭包(Closure),闭包是这些东西共同的组合。
纯函数
相同的输入永远会得到相同的输出,而且没有任何可观察的副作用。
纯函数就类似数学中的函数(用来描述输入和输出之间的关系),y = sin(x)。
- 函数式编程不会保留计算中间的结果,所以变量是不可变的(无状态的)
- 我们也可以把一个函数的执行结果交给另一个函数处理
let numbers = [1, 2, 3, 4, 5]
// 纯函数 对于相同的函数,输出是一样的
// slice方法,截取的时候返回截取的函数,不影响原数组
numbers.slice(0, 3) // => [1, 2, 3]
numbers.slice(0, 3) // => [1, 2, 3]
numbers.slice(0, 3) // => [1, 2, 3]
// 不纯的函数 对于相同的输入,输出是不一样的
// splice方法,返回原数组,改变原数组
numbers.splice(0, 3) // => [1, 2, 3]
numbers.splice(0, 3) // => [4, 5]
numbers.splice(0, 3) // => []
// 这也是一个纯函数
function getSum (n1, n2) {
return n1 + n2
}
console.log(getSum(1, 2)) // 3
console.log(getSum(1, 2)) // 3
console.log(getSum(1, 2)) // 3
纯函数的好处
- 可缓存
- 可测试
- 可并行处理
- 无副作用