Redux观点之四: reducer(归结函数)与纯函数

reducer(归结函数)

reducer(归结函数)这类函数的称号,是由数组的一个迭代要领reduce(归结)而来,你能够参考MDN中的相干申明:

在JS语言中的数组reduce(归结)这个要领是一种运用于特别状况的迭代要领,它能够借由一个回调(callback)函数,来作前后值两相运算,然后不停缩减数组中的成员数目,终究返回一个值。reduce(归结)并不会更行动为传入的数组(挪用reduce的数组),所以它也没有副作用。一个简朴的例子以下:

const aArray = [0, 1, 2, 3, 4, 5]

const sum = aArray.reduce(function(pValue, value, index, array){
    return pValue + value
})

console.log(sum) // 15

数组的reduce(归结)要领,另有另一种语法款式,是带有初始值的,这会比较靠近Redux中的reducer款式,以下面的例子:

const initialState = 0

const sum = [1, 2, 3, 4, 5].reduce(add, initialState)

function add(a, b) {
    // `a` 代表前一个状况
    // `b` 代表如今在数组中的项目
    return a + b
}

console.log(sum) // 15

reduce(归结)要领具有疏散运算的特性,罕见于下面几种运用当中:

  • 两相比较末了掏出特定的值(最大或最小值)

  • 盘算一切成员(值),总合或相乘

  • 别的须要两两处置惩罚的状况(组合巢状数组等等)

不过,Redux中的reducer与数组中的reduce要领并不雷同,个中最大的差别,是reducer并非对一全部列表举行归结运算,而是对一个action(行动)与如今的state举行归结运算,回传出新的state。

副作用与纯函数

当一个函数是纯函数时,我们能够说输出只取决于输入

关于函数来讲,具有副作用代表着能够会更动到外部环境,或是更动到传入的参数值。函数的辨别是以 纯(pure)函数 与 不纯(impure)函数 二者来辨别,但这不光只需无副作用的差别,另有其他的前提。纯函数(pure function)即满足以下三个前提的函数,以下的定义是来自于Redux的观点:

  • 给定雷同的输入(传入值),一定会返回雷同输出值效果(返回值)

  • 不会发生副作用

  • 不依靠任何外部的状况

一个典范的纯函数的例子以下:

const sum = function(value1, value2) {
  return value1 + value2
}

套用上面说的前提定义,你能够用下面视察来明白它是不是一个纯函数:

  • 只需每次给定雷同的输入值,就一定会获得雷同的输出值: 比方传入1与2,就一定会获得3

  • 不会转变原始输入参数,或是外部的环境,所以没有副作用

  • 不依頼其他外部的状况,变量或常量

那什么又是一个不纯的函数?看以下的例子就是,它须要依靠外部的状况/变量值:

let count = 1

let increaseAge = function(value) {
  return count += value
}

在JavaScript中不纯函数很罕见,像我们一向用来作为输出的console.log函数,或是你能够会在很多例子看到的alert函数,都是”不”纯函数,这类函数平常没有返回值,都是用来作某件事,像console.log会更动浏览器的主控台(外部环境)的输出,也算是一种副作用。

每次输出值都差别的不纯函数一类,最典范的就是Math.random,这是发生随机值的内建函数,既然是随机值固然每次运转的返回值都不一样。

比方在数组的内建要领中,有一些是有副作用,而有一些是无副作用的,这个部分须要查对应API才够清晰。不会转变传入的数组的,会在作完某件预先返回一个新数组的要领,就是无副作用的纯函数(要领),而会转变原数组就算是不纯函数(要领)了。

下面是两个在数组中作一样事变的差别要领,都是要掏出只包括数组的前三个成员的数组。一个用splice,另一用是slice,看起来都很像,连这两个要领的称号都很像,但倒是完整属于差别的品种:

// 不地道(impure),splice会转变到原数组
const firstThree = function(arr) {
  return arr.splice(0,3)
}

// 地道(pure),slice会返回新数组
const firstThree = function(arr) {
  return arr.slice(0,3)
}

其他有很多内建的或经常运用的函数都是免不了有副作用的,比方这些运用:

  • 会转变传参(对象、数组)的函数(要领)

  • 时候性子的函数,setTimeout等等

  • I/O相干

  • 数据库相干

  • AJAX

纯函数固然有它的迥殊的长处:

  • 代码浏览性进步

  • 较为关闭与牢固,可重复运用性高

  • 输出输入纯真,易于测试、调试

  • 由于输入->输出效果牢固,能够缓存或作影象处置惩罚,在高消费的运用中可作进步运转效力的机制

末了,并非说有副作用的函数就不要运用,而且要很清晰的明白这个观点,然后尽量在你本身的撰写的平常功用函数上运用纯函数,以及让必要有副作用的函数获得优越的管控。如今已经有一些新式的函数库或框架(比方Redux),会迥殊强迫请求在某些处所只能运用纯函数,而具有副作用的不纯函数只能在特定的状况下才运用。

注: 虽然在副作用与纯函数的引见中,我们有提到一些挪用外部API(console.log/alert)、时候(Date())、随机(Math.random)也属于有副作用的挪用,但以品级来辨别它们只算是”轻度”或”微量”的副作用,这些在reducer或Action Creators能不能用?答案是能够用但也不要用,它会影响到纯函数的一些优化。以在副作用的主题来讲,异步运转才是”中度”或”平常”品级的副作用,我们谈到副作用平常是指这个品级的。固然也有”重度”品级的副作用,那是另一个条理的特别运用状况议论,比方组合出来的庞杂异步运转流程构造。

    原文作者:eyesofkids
    原文地址: https://segmentfault.com/a/1190000008210097
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞