JavaScript 纯函数

纯函数

第一次据说"纯函数(Pure Function)"这个术语时, 我也是比较疑惑的. 啥是纯函数? 为何要使用纯函数? 以及和普通的JavaScript函数有什么区别吗?编程

带着这些疑问, 一块儿来看下.markdown

什么是纯函数?

定义

  • 若是函数的调用参数相同, 则永远返回相同的结果. 它不依赖于程序执行期间函数外部任何状态或数据的变化, 只依赖于传入的参数
  • 纯函数不会产生任何可观察的反作用, 例如: 网络请求, 输入/输出设备, 或数据突变(mutation)等

若是一个函数符合上述2个要求, 它就是纯函数.网络

什么是可观察的反作用?

一个能够被观察的反作用是在函数内部与该函数外部的任意交互. 如: 在函数内修改外部的变量, 或在函数内调用另一个函数等等.dom

若是纯函数调用纯函数, 不会产生反作用, 依然是纯函数函数式编程

可被观察的反作用, 包括但不限于:函数

  • 进行一个HTTP请求
  • Mutating Data
  • 输出数据到屏幕或控制台
  • DOM 查询或操做
  • Math.random()
  • 获取当前时间
  • ...

反作用自己并无什么很差, 在某些场景每每是必需的. 但对于要保持纯函数, 它不能包含任何反作用. 固然, 并不是全部函数都必须是纯函数.oop

纯函数 示例

function sqrt(a) {
  return a * a
}
复制代码

该函数符合咱们所说的2条纯函数的定义, 不依赖于任何外部输入, 不改变任何外部数据, 没有反作用. 每次输入一样的参数, 永远会获取相同的结果, 且不随程序执行的时机而有变化.单元测试

非纯函数 示例

function getName(obj){    
  return obj.name;
}
function getAge(obj){  
  return obj.age;
}
function sayHi(person){  
  console.log('I am' + getName(person) + ',and I am' + getAge(person) + 'years old');
  }
  
var Tom = {  name: 'TOM',  age: 26};

sayHi(Tom);
复制代码

sayHi不是纯函数,它依赖于getNamegetAge两个函数,若不当心或因业务须要, 必须要改变其中某个函数的功能,这将使得sayHi这个函数出现错误。 当网页变得复杂,且由多人维护的时候,bug调试会变得很是复杂。测试

纯函数的优势

纯函数在函数式编程中被大量使用, 诸如React.jsRedux等库都须要使用纯函数.ui

纯函数能够用在日常的JavaScript开发中使用, 也能够混合纯函数和非纯函数一块儿使用, 不必定非要限定某个编程范例中必须使用纯函数.

并不是全部的函数都须要纯函数. 例如: 操做DOM的事件处理函数就不适合使用纯函数. 不过, 这种事件处理函数, 能够调用其余纯函数来处理, 以此减小项目中不纯函数的数量.

使用纯函数的主要缘由是可测试性和重构

可测试性

纯函数很是容易进行单元测试,由于不须要考虑上下文环境,只须要考虑输入和输出, 若是传入相同的参数, 它们将始终产生相同的结果.

重构

纯函数还会使得维护和重构代码变容易.

你能够放心的重构一个函数, 没必要担忧没注意到的反作用, 而致使整个应用调试复杂/困难.

::: warning 若是项目中, 充斥着反作用, 那么函数/模块之间的逻辑可能互相交织耦合, 在后期新增逻辑时, 可能因为依赖复杂而难以重构.

更常见的是, 开发为了应付需求, 而不断引入新的反作用到本来的逻辑上, 从而致使代码变得愈来愈糟糕. :::

正确地使用纯函数, 能够生产更高质量的代码, 而且也是一种更加干净的编码方式.

此外, 纯函数不是JavaScript的专利. 想要了解更多内容, 能够查阅PureFunction-wiki

可移植性 / 自文档化(Portable / Self-Documenting)

因为纯函数是自给自足的,它须要的东西都在输入参数中已经声明,因此它能够任意移植到任何地方。

相关连接

相关文章
相关标签/搜索