关闭

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

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

当我第一次听到 “纯函数 (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 


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: http://www.fly63.com/article/detial/1274

CSS calc()函数的用法

CSS3 的 calc() 函数允许我们在属性值中执行数学操作。例如,我们可以使用 calc() 指定一个元素宽的固定像素值为多个数值的和。如果你使用过 CSS 预处理器,比如 SASS

如何实现 lodash.get 函数及可选链操作简化取值

lodash 基本上成为了 js 项目的标配工具函数,广泛应用在各种服务端以及前端应用中,但是它的包体积略大了一些。对于服务端来说,包的体积并不是十分的重要,或者换句话说,不像前端那样对包的体积特别敏感,一分一毫都会影响页面打开的性能,从而影响用户体验。

Js函数的扩展

篇文章主要介绍了函数的扩展,函数的扩展只要有三个方面:参数的默认值,箭头函数.关于尾调用的优化;1:参数的默认值(会形成一个单独的作用域)

JavaScript 自己写一个 replaceAll() 函数

JavaScript 的 replace() 方法可以在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。但是,只输入字符串的话,仅替换第一个字符,当然也可以用正则表达式来进行全局替换:

引用类型作为函数参数何解

在向函数传递引用类型的参数时,相当于把引用类型的地址复制给函数内的一个局部变量,所以局部变量和传入的参数会指向内存中的同一个对象。 局部变量的变化也会映射到传入参数

Js函数记忆

函数记忆是一种编程技巧,通过牺牲算法的空间复杂度以换取更优的时间复杂度。定义: 若传递的参数一致,则通过缓存读取存取计算结果的一种编程技巧

ES6中箭头函数

ES6 允许使用“箭头”(=>)定义函数。如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

js实现KB、MB、GB、TB单位转换

当函数参数值小于等于1000时,参数除以1000,即可得到最小单位kb,赋值给变量_integer;当_integer值大于1000时,kb值除以1000,即可得到mb,赋值给变量_integer;以此类推。

JavaScript 函数式编程

我理解的 JavaScript 函数式编程,都认为属于函数式编程的范畴,只要他们是以函数作为主要载体的。

js之惰性函数

惰性函数是js函数式编程的另一个应用,惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,他的应用情景在于当我们遇到一个需要判断场景去调用不同的方法时,避免重复进入函数内的if判断,也就是说if判断只进行一次,之后函数就会被分支里的代码替换掉

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!