什么是纯函数_以及为什么要用纯函数?

时间: 2018-11-07阅读: 39标签: 函数

当我第一次听到 “纯函数 (Pure Function)” 这个术语的时候我很疑惑。常规的函数做错了什么?为什么要变纯? 为什么我需要纯的函数?

除非你已经知道什么是纯函数,否则你可能会问同样的疑惑。不过这个概念其实很简单。我们可以花个 5 分钟一起来看以下。


什么函数是纯的?

纯函数的定义是:

  1. 如果函数的调用参数相同,则永远返回相同的结果。它不依赖于程序执行期间函数外部任何状态或数据的变化,必须只依赖于其输入参数。

  2. 该函数不会产生任何可观察的副作用,例如网络请求,输入和输出设备或数据突变(mutation)。

这就是纯的函数。 如果一个函数符合上述 2 个要求,它就是纯函数。 你可能在过去甚至无意地情况下编写过纯函数。

在我们研究一个函数一个纯或不纯之前,让我们先讨论一下可怕的“副作用”。


什么是可观察的副作用?

一个可以被观察的副作用是在函数内部与其外部的任意交互。这可能是在函数内修改外部的变量,或者在函数里调用另外一个函数等。

注: 如果纯函数调用纯函数,则不产生副作用依旧是纯函数。

副作用来自,但不限于:

  • 进行一个 HTTP 请求

  • Mutating data

  • 输出数据到屏幕或者控制台

  • DOM 查询/操作

  • Math.random()

  • 获取的当前时间

副作用本身并不是毒药,某些时候往往是必需的。 但是,对于要保持纯粹的函数,它不能包含任何副作用。当然,并非所有函数都需要是纯函数。 我将在稍后讨论这个情况。

不过首先,让我们来看一些纯的和不纯的函数对比的例子......


纯函数的例子

以下是一个计算产品税后价格(英国税率是20%)的纯函数的例子:

function priceAfterTax(productPrice) { return (productPrice * 0.20) + productPrice;}

它符合我们所说的两条纯函数的定义。不依赖于任何外部输入,不改变任何外部数据、没有副作用。

即使你用同样的输入运行运行这个函数 100,000,000 次它依旧产生同样的结果


非纯函数

我们已经看了纯函数的例子,现在一起来看一个非纯函数(Impure function)的 JavaScript 例子:

var tax = 20;
function calculateTax(productPrice) {
    return (productPrice * (tax/100)) + productPrice;
}

暂停片刻,看看你是否能看出为什么这个函数不纯。

其中函数的计算结果取决于外部 tax 变量,而纯函数不能依赖外部变量。它没有满足定义中的第一个要求,因此这个函数是不纯的。


为什么说纯函数在 JavaScript 很重要?

纯函数在函数式编程中被大量使用。而且诸如 ReactJS 和 Redux 等优质的库都需要使用纯函数。

不过,纯函数也可以用在平常的 JavaScript 开发中使用,不一定要限死在某个编程范例中。 你可以混合纯的和不纯的函数,这完全没问题。

并非所有函数都需要是纯的。 例如,操作 DOM 的按钮按下的事件处理程序就不适合纯函数。 不过,这种事件处理函数可以调用其他纯函数来处理,以此减少项目中不纯函数的数量。


可测试性和重构

另一个使用纯函数的原因是测试以及重构。

使用纯函数的一个主要好处是它们可以直接测。 如果传入相同的参数,它们将始终产生相同的结果。

同时纯函数还使得维护和重构代码变得更加容易。你可以放心地重构一个纯函数,不必操心没注意到的副作用搞乱了整个应用而导致终调试地狱。(译注:如果项目中充斥着副作用,那么函数/模块之间的逻辑可能互相交织耦合,在后期新增逻辑时可能由于依赖复杂而难以重构,更常见的是开发为了应付需求而不断的引入新的副作用到原本的逻辑上从而导致代码变得越来越糟糕。)

正确地使用纯函数可以产生更加高质量的代码。并且也是一种更加干净的编码方式。

此外,纯函数不不是 JavaScript 的专利。想要了解更多内容可以参见 Wiki。同时也推荐阅读 开发建议手册 以及 纯函数 vs. 非纯函数.

原文链接: medium.com 
翻译来源:https://www.zcfy.cc/article/javascript-what-are-pure-functions-and-why-use-them 


什么时候不能使用箭头函数?

JS中对象方法的定义方式是在对象上定义一个指向函数的属性,当方法被调用的时候,方法内的this就会指向方法所属的对象:定义字面量方法、定义原型方法、定义事件回调函数、定义构造函数、追求过短的代码

JavaScript push() 方法详解

push() 方法主要用于向数组的末尾添加一个或多个元素,其返回值为添加后新的长度,即push后的数组长度,该值为number类型。介绍:一个数组中添加新元素、把一个数组的值赋值到另一个数组上、在对象使用push

什么是函数的副作用——理解js编程中函数的副作用

函数副作用是指当调用函数时,除了返回函数值之外,还对主调用函数产生附加的影响。副作用的函数不仅仅只是返回了一个值,而且还做了其他的事情

js中sort函数用法总结_sort排序算法原理

js中sort方法用于对数组的元素进行排序,并返回数组。默认排序顺序是根据字符串Unicode码点。如果要得到自己想要的结果,不管是升序还是降序,就需要提供比较函数了。该函数比较两个值的大小,然后返回一个用于说明这两个值的相对顺序的数字

“回调函数”超难面试题!!

进来的小伙伴可以先自己思考一下 。对于还属于小白的我来说扫了一眼这些代码的反应是:这都是什么鬼?但是我也比较喜欢钻研~ 仔细看了第二眼的反应是:这回调函数也太回调了吧

js函数内部两个特殊的对象之arguments和this

arguments是一个类数组对象。包含着传入函数中的所有参数。但这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。this引用的是函数执行的环境对象(当在网页的全局作用域中调用函数时,this对象引用的就是window)

js中函数声明、函数表达式、匿名函数的理解和区别?

js和其他编程语言相对比较随意,首先来理解下函数基本概念:函数声明、函数表达式、匿名函数。函数声明和函数表达式区别有哪些?

js中的立即执行函数的写法,立即执行函数作用是什么?

这篇文章主要讲解:js立即执行函数是什么?js使用立即执行函数有什么作用呢?js立即执行函数的写法有哪些?

js在excel的编写_excel支持使用JavaScript自定义函数编写

微软 称excel就实现面向开发者的功能,也就是说我们不仅可以全新定义的公式,还可以重新定义excel的内置函数,现在Excel自定义函数增加了使用 JavaScript 编写的支持,下面就简单介绍下如何使用js来编写excel自定义函数。

JavaScript中函数的三种定义方法

函数的三种定义方法分别是:函数定义语句、函数直接量表达式和Function()构造函数的方法,下面依次介绍这几种方法具体怎么实现,在实际编程中,Function()构造函数很少用到,前两中定义方法使用比较普遍。