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

但在开始之前,我们先用一节的课程来介绍一下一个函数式编程里面非常重要的概念 —— 纯函数(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 往控制台打印数据也是副作用。

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

总结

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

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

下一节:动手实现 Redux(四):共享结构的对象提高性能

上一节:动手实现 Redux(二):抽离 store 和监控数据变化

动手实现 Redux(三):纯函数(Pure Function)简介的更多相关文章

  1. Function Programming - 纯函数(Pure Function)

    纯函数的定义,非常重要!! Pure function 意指相同的输入,永远会得到相同的输出,而且没有任何显著的副作用. 老样子,我们还是从最简单的栗子开始: var minimum = 21; va ...

  2. 什么叫pure function(纯函数)

    (来自:http://en.wikipedia.org/wiki/Pure_function) 在计算机编程中,假如满足下面这两个句子的约束,一个函数可能被描述为一个纯函数: 给出同样的参数值,该函数 ...

  3. redux中的reducer为什么必须(最好)是纯函数

    为什么reducer最好是纯函数? 首先你得看看文档怎么说reducer的作用的,‘接收旧的 state 和 action,返回新的 state’,他起的是一个对数据做简单处理后返回state的作用. ...

  4. 动手实现 Redux(四):共享结构的对象提高性能

    接下来两节某些地方可能会稍微有一点点抽象,但是我会尽可能用简单的方式进行讲解.如果你觉得理解起来有点困难,可以把这几节多读多理解几遍,其实我们一路走来都是符合“逻辑”的,都是发现问题.思考问题.优化代 ...

  5. 动手实现 Redux(二):抽离 store 和监控数据变化

    上一节 的我们有了 appState 和 dispatch: let appState = { title: { text: 'React.js 小书', color: 'red', }, conte ...

  6. 动手实现 Redux(五):不要问为什么的 reducer

    经过了这么多节的优化,我们有了一个很通用的 createStore: function createStore (state, stateChanger) { const listeners = [] ...

  7. react事件绑定的三种常见方式以及解决Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state问题思路

    在 React 组件中,每个方法的上下文都会指向该组件的实例,即自动绑定 this 为当前组件. 而且 React 还会对这种引用进行缓存,以达到 CPU 和内存的优化.在使用 ES6 classes ...

  8. 动手实现 Redux(六):Redux 总结

    不知不觉地,到这里大家不仅仅已经掌握了 Redux,而且还自己动手写了一个 Redux.我们从一个非常原始的代码开始,不停地在发现问题.解决问题.优化代码的过程中进行推演,最后把 Redux 模式自己 ...

  9. react_结合 redux - 高阶函数 - 高阶组件 - 前端、后台项目打包运行

    Redux 独立的集中式状态管理 js 库 - 参见 My Git 不是 react 库,可以与 angular.vue 配合使用,通常和 react 用 yarn add redux import ...

随机推荐

  1. 新产品为了效果,做的比較炫,用了非常多的图片和JS,所曾经端的性能是非常大的问题,分篇记录前端性能优化的一些小经验。

    第一篇:HTTPserver 因tomcat处理静态资源的速度比較慢,所以首先想到的就是把全部静态资源(JS,CSS,image,swf) 提到单独的server,用更加高速的HTTPserver,这 ...

  2. bzoj4149: [AMPPZ2014]Global Warming

    头都烂了怎么头疼啊 考虑先做出对于一个位置以它作为唯一最小值的最远区间,这个可以单调栈上二分搞出来 那么对于一个位置这个区间而言,一定是选择这个区间的最大数是作为最终的唯一最大数最优的 为什么呢?我们 ...

  3. dedecms5.7二级域名文章图片不显示修改方法.相对路径改为绝对路径的方法

    dedecms5.7(织梦CMS5.7)二级域名文章图片不显示修改方法.相对路径改为绝对路径的方法 dedecms升级到5.7SP1后,开启二级域名,你会发现,在二级域名下的文章,上传的图片地址都是: ...

  4. Mysql语句示例

    Mysql语句示例 最常用 sql 语句总结 前言 Mysql 是数据库开发使用的主要平台之一.sql 的学习掌握与使用是数据库开发的基础,此处展示详细sql 语句的写法,及各种功能下的 sql 语句 ...

  5. java中匹配中文的正则表达式

    java中要匹配中文的正则表达式可以有两种写法:一是使用unicode中文码:二是直接使用汉字字符: 例: (1)String str = "晴"; String regexStr ...

  6. I.MX6 新版u-boot分析

    /******************************************************************* * I.MX6 新版u-boot分析 * 说明: * 因为一些 ...

  7. NFS (网络文件系统)

    NFS (网络文件系统) https://www.cnblogs.com/wahaha02/p/9559345.html Linux网络文件系统的实现与调试 NFS协议 NFS (网络文件系统)不是传 ...

  8. 【USACO06NOV】路障

    [题目链接] 点击打开链接 [算法] 最短路 [代码] #include<bits/stdc++.h> using namespace std; #define MAXN 5000 #de ...

  9. 【NOI 2005】 维修数列

    [题目链接] 点击打开链接 [算法] 本题所运用的也是Splay的区间操作,但是实现较为困难 INSERT操作             将pos splay至根节点,pos+1 splay至根节点的右 ...

  10. @font-face 用fontsquirrel把ttf文件获取别的文件格式

    @font-face是css3的一个模块,但是@font-face这个功能早在IE4就支持了,他主要是把自己定义的Web字体嵌入到你的网页中, @font-face { font-family: &l ...