我们接下来会继续优化我们的 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. Axure Base 02

    (二)Axure rp的线框图元件 l  图片 图片元件拖入编辑区后,可以通过双击选择本地磁盘中的图片,将图片载入到编辑区,axure会自动提示将大图片进行优化,以避免原型文件过大:选择图片时可以选择 ...

  2. umask文件屏蔽字的使用【学习笔记】

    #include "apue.h" #include <fcntl.h> #define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP ...

  3. 【转】cocos2dx 内存管理机制

    原文地址: http://www.zaojiahua.com/memory-management.html cocos2dx采用的是在堆上分配内存空间,想想看你在写程序的时候对于cocos2dx中的类 ...

  4. VC链接hid.lib出错问题解决方案

    写一个HID的客户端小程序,调用了一些HID API,但是链接时出现了奇怪的现象. 尽管我已经把头文件和lib文件加入到了VC的Include和Lib目录中,但不管我用VC链接,还是在DDK环境下链接 ...

  5. CS231n 2016 通关 第二章-KNN 作业分析

    KNN作业要求: 1.掌握KNN算法原理 2.实现具体K值的KNN算法 3.实现对K值的交叉验证 1.KNN原理见上一小节 2.实现KNN 过程分两步: 1.计算测试集与训练集的距离 2.通过比较la ...

  6. 使用JavaScript实现弹出层效果的简单实例

    转自:https://www.jb51.net/article/85475.htm 实现弹出层效果的思路非常简单:将待显示的内容先隐藏,在触发某种条件后(如点击按钮),将原本隐藏的内容显示出来. 实现 ...

  7. 016--python文件处理

    一.操作文件流程 1.打开文件,得到文件句柄并赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 示例代码: f = open('chenli.txt') #打开文件 first_line = ...

  8. Django View类的解析

    class View(object): """ Intentionally simple parent class for all views. Only impleme ...

  9. (水题)洛谷 - P1996 - 约瑟夫问题 - 链表

    https://www.luogu.org/problemnew/show/P1996 试了一下数组实现的双向链表,是挺难用的,估计是应该写个get_next()函数比直接用next数组好. #inc ...

  10. python 高阶函数一 概念

    一.2个概念: 1.变量可以指向函数本身 >>> abs <built-in function abs> >>> f = abs >>> ...