1.什么是函数式编程
我们用简单的技术术语定义函数式编程的话,可以说,函数式编程时一种范式,我们能以此创建仅依赖输入就可以完成自身逻辑的函数,这可以保证函数在多次调用时,仍返回相同的结果。函数不会改变外部环境的任何变量,这就会产生可以缓存、可测试的代码库。
这里我们说一下函数和方法的区别:
简单来说:
函数是一段可通过其名称被调用的代码。它可以传递参数并返回值
方法是一段必须通过其名称及其关联对象来调用的代码
//非真正函数
const num = 5
const sum1 = value => {
return value + num
}
//真正函数
const sum2 = (value, num) => {
return value + num
}
//一个简单的函数
const fn = a => {
return a
}
fn(1) //名称调用
//一个简单的方法
const obj = {
b: a => {
return a
},
}
obj.b(1) //名称及关联对象调用
1.2 引用透明性
所有的函数对于相同的输入都返回相同的值。函数的这一属性为并发代码和缓存带来可能性。简单来说就是它不需要依赖全局的数据,就可以在线程上自由运行,没有任何的锁的机制,而且相同的输入返回相同的结果,我们就可以将相同的缓存。这个我们说完纯函数会详细说明。
1.3 命令式、声明式与抽象
首先我们要区分命令式和声明式的区别,以下代码举例:
const arr = [1, 2, 3]
//命令式
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
//声明式
arr.forEach(item => console.log(item))
命令式编程就是在告诉编译器如何做,而声明式就是告诉编译器做什么。函数式编程主张以声明式编程和编写抽象的代码(为了代码在其他的地方复用方便)。
1.4纯函数
下面我们就来说下一下重点中的重点:纯函数。经过上面第一节的介绍,我们可以明确纯函数的含义。纯函数就是给定的输入返回相同的结果。纯函数的一个重要属性就是不改变任何外部的变量,简单来说就是不依赖任何外部变量。
如果一个函数调用时改变了外部的变量,而另一个函数的逻辑依赖于这个外部变量,那么这会使代码库变得非常的难以测试,这不是我们希望看到的结果。所以我们需要纯函数来有助于我们进行测试。然后我们在命名纯函数的时候(其实不管是不是纯函数都要确保)命名必须要有真实的意义。必要以aa,bb来命名。比如简单来说,Math.max(1,2,3),我想这个看一下就知道结果了吧,纯函数就是利于阅读,理解和测试。
1.5 并发代码
纯函数总是允许并发的执行代码,因为不会改变外部的变量所以不用担心他的同步问题。当然js并没有多线程来并发执行函数,但是如果式node或者webworker呢?
let global = 'something'
const fn1 = value => {
global = 'somethingElse'
}
const fn2 = () => {
if (global === 'something') {
//...
}
}
如果需要并发执行fn1和fn2,假如线程一(T-1)选择fn1,线程二(T-2)选择fn2,如果T-1在T-2之前执行,由于两个函数都依赖于全局的变量golbal如果并发执行,会产生不良的影响。但是如果我们将他们换成纯函数:
//换成纯函数
const fn1 = (value, global) => {
global = 'somethingElse'
}
const fn2 = global => {
if (global === 'something') {
//...
}
}
现在这两个函数不依赖于外部变量,不用担心线程问题,就可以并发执行了,不用担心任何问题。
1.6 可缓存
之前我们说过,纯函数给定的输入返回相同的结果,那么我们就不需要多次输入来反复调用这个函数了。我根据他的引用透明性来给定一个obj,让他记录所有的输入(key)和输出(value),我们在调用函数的时候只要先去obj中判断是否存在,如果存在就在obj中取出相应的value就可以了,如果不存在,才考虑去调用这个函数。
const fn = key => {
//一个非常复杂耗时的过程,并return 结果
}
const obj = { 1: 2, 2: 3, 3: 4 }
//我们先检查key是否在obj里面,如果在就返回相应的value,不在就执行函数并添加进obj中
obj.hasOwnProperty(key) ? obj[key] : (obj[key] = fn(key))
这样看起来纯函数是不是很爽,一点点的代码就可以使函数调用可缓存。
1.7纯函数和数学函数
首先我们了解一下数学函数的定义:这是我在各个文库中观看以后截取的
所以我们可以简单的来说,纯函数就是数学函数。
1.8 JavaScript是函数式编程语言吗
这个问题比较难说,可以说是也可以说不是。主要是因为js不是一种纯函数语言,更像是一种多规范语言。只是js比较适合函数式编程的规范。js将函数的优先级提到最高,所以无论是将函数作为参数,还是将函数传递给另一个函数,js都是可以支持的。所以将js视为一种函数式编程语言也是没问题的。