动手实现 Redux(三):纯函数(Pure Function)简介

咱们接下来会继续优化咱们的 createStore 的模式,让它使咱们的应用程序得到更好的性能。html

但在开始以前,咱们先用一节的课程来介绍一下一个函数式编程里面很是重要的概念 —— 纯函数(Pure Function)。编程

简单来讲,一个函数的返回结果只依赖于它的参数,而且在执行过程里面没有反作用,咱们就把这个函数叫作纯函数。这么说确定比较抽象,咱们把它掰开来看:数组

  1. 函数的返回结果只依赖于它的参数。
  2. 函数执行过程里面没有反作用。

函数的返回结果只依赖于它的参数

const a = 1
const foo = (b) => a + b
foo(2) // => 3

foo 函数不是一个纯函数,由于它返回的结果依赖于外部变量 a,咱们在不知道 a的值的状况下,并不能保证 foo(2) 的返回值是 3。虽然 foo 函数的代码实现并无变化,传入的参数也没有变化,但它的返回值倒是不可预料的,如今 foo(2) 是 3,可能过了一会就是 4 了,由于 a 可能发生了变化变成了 2。浏览器

const a = 1
const foo = (x, b) => x + b
foo(1, 2) // => 3

如今 foo 的返回结果只依赖于它的参数 x 和 bfoo(1, 2) 永远是 3。今天是 3,明天也是 3,在服务器跑是 3,在客户端跑也 3,无论你外部发生了什么变化,foo(1, 2) 永远是 3。只要 foo 代码不改变,你传入的参数是肯定的,那么 foo(1, 2) 的值永远是可预料的。服务器

这就是纯函数的第一个条件:一个函数的返回结果只依赖于它的参数。函数式编程

函数执行过程没有反作用

一个函数执行过程对产生了外部可观察的变化那么就说这个函数是有反作用的。函数

咱们修改一下 foo性能

const a = 1
const foo = (obj, b) => {
  return obj.x + b
}
const counter = { x: 1 }
foo(counter, 2) // => 3
counter.x // => 1

咱们把原来的 x 换成了 obj,我如今能够往里面传一个对象进行计算,计算的过程里面并不会对传入的对象进行修改,计算先后的 counter 不会发生任何变化,计算前是 1,计算后也是 1,它如今是纯的。可是我再稍微修改一下它:测试

const a = 1
const foo = (obj, b) => {
  obj.x = 2
  return obj.x + b
}
const counter = { x: 1 }
foo(counter, 2) // => 4
counter.x // => 2

如今状况发生了变化,我在 foo 内部加了一句 obj.x = 2,计算前 counter.x 是 1,可是计算之后 counter.x 是 2。foo 函数的执行对外部的 counter 产生了影响,它产生了反作用,由于它修改了外部传进来的对象,如今它是不纯的。优化

可是你在函数内部构建的变量,而后进行数据的修改不是反作用:

const foo = (b) => {
  const obj = { x: 1 }
  obj.x = 2
  return obj.x + b
}

虽然 foo 函数内部修改了 obj,可是 obj 是内部变量,外部程序根本观察不到,修改 obj 并不会产生外部可观察的变化,这个函数是没有反作用的,所以它是一个纯函数。

除了修改外部的变量,一个函数在执行过程当中还有不少方式产生外部可观察的变化,好比说调用 DOM API 修改页面,或者你发送了 Ajax 请求,还有调用 window.reload刷新浏览器,甚至是 console.log 往控制台打印数据也是反作用。

纯函数很严格,也就是说你几乎除了计算数据之外什么都不能干,计算的时候还不能依赖除了函数参数之外的数据。

总结

一个函数的返回结果只依赖于它的参数,而且在执行过程里面没有反作用,咱们就把这个函数叫作纯函数。

为何要煞费苦心地构建纯函数?由于纯函数很是“靠谱”,执行一个纯函数你不用担忧它会干什么坏事,它不会产生不可预料的行为,也不会对外部产生影响。无论什么时候何地,你给它什么它就会乖乖地吐出什么。若是你的应用程序大多数函数都是由纯函数组成,那么你的程序测试、调试起来会很是方便。

相关文章
相关标签/搜索