浅析 FP:JavaScript 中的纯函数

前言

纯函数 是一个常见的概念,在平常工做中也常常会遇到,它其实很是简单,今天咱们来了解一下它的好处以及为何要使用它。git

两个特色

一个函数,若是符合如下两个特色,那么它就能够称之为 纯函数编程

  1. 对于相同的输入,永远获得相同的输出
  2. 没有任何可观察到的反作用

相同输入获得相同输出

咱们先来看一个不纯的反面典型:api

let greeting = 'Hello'

function greet (name) {
  return greeting + ' ' + name
}

console.log(greet('World')) // Hello World

上面的代码中,greet('World'),是否是永远返回 Hello World ? 显然不是,假如咱们修改 greeting 的值,就会影响 greet 函数的输出。即函数 greet 实际上是 依赖外部状态 的。缓存

那咱们作如下修改:ide

function greet (greeting, name) {
  return greeting + ' ' + name
}

console.log(greet('Hi', 'Savo')) // Hi Savo

greeting 参数也传入,这样对于任何输入参数,都有与之对应的惟一的输出参数了,该函数就符合了第一个特色。函数式编程

没有反作用

反作用的意思是,这个函数的运行,不会修改外部的状态函数

下面再看反面典型:单元测试

const user = {
  username: 'savokiss'
}

let isValid = false

function validate (user) {
  if (user.username.length > 4) {
    isValid = true
  }
}

可见,执行函数的时候会修改到 isValid 的值(注意:若是你的函数没有任何返回值,那么它极可能就具备反作用!)测试

那么咱们如何移除这个反作用呢?其实不须要修改外部的 isValid 变量,咱们只须要在函数中将验证的结果 return 出来:ui

const user = {
  username: 'savokiss'
}

function validate (user) {
  return user.username.length > 4;
}

const isValid = validate(user)

这样 validate 函数就不会修改任何外部的状态了~

为何要用纯函数?

你可能听过 纯函数 有很多优势,若是你经手过各类难维护的函数,你就更应该考虑使用 纯函数

可测试性(Testable)

让咱们先用不纯的 greet 方法来作单元测试:

// jest 语法
describe('greet', function() {
  it('shows a greeting', function() {
    expect(greet('Savo')).toEqual('Hello Savo')
  });
});

若是咱们修改了 greeting 变量为 Hi,上面的测试就会失败了,这本质上不该该发生。

那咱们若是换成纯函数版本的 greet ,全部都是那么天然~ 只须要修改单元测试中传入的参数便可!

可缓存性(Cacheable)

纯函数能够根据输入来作缓存。实现缓存的是一种叫做 memorize 的技术。

下面的代码来自 Vue 源码:

/**
 * Create a cached version of a pure function.
 * 只适用于缓存 接收一个字符串为参数的 fn
 */
export function cached (fn) {
  const cache = Object.create(null)
  return function cachedFn (str) {
    const hit = cache[str]
    return hit || (cache[str] = fn(str))
  }
}

/**
 * Capitalize a string.
 */
export const capitalize = cached((str) => {
  return str.charAt(0).toUpperCase() + str.slice(1)
})

capitalize 即为缓存后的函数,若是屡次调用就会返回缓存后的值,从而节省计算资源,而这一切的前提都创建在传入 cached 中的那个函数为纯函数的基础上。

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

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

而且纯函数对于本身的依赖是 诚实的,这一点你看它的 形参 就知道啦~正所谓 形参起的好,注释不用搞~(双押!)纯函数就是这么个正直的小可爱~

总结

好啦,咱们已经大概了解了纯函数,它对于咱们写出良好代码有着重要的意义,同时也是函数式编程中的精髓。原本本篇是想单纯介绍纯函数的,可是想起来了柯里化 (curry) 也没有讲过,那么下次有机会就讲一讲柯里化吧~

We'll see!

参考连接


本文首发于公众号:码力全开(codingonfire)

本文随意转载哈,注明原文连接便可,公号文章转载联系我开白名单就好~

codingonfire.jpg

相关文章
相关标签/搜索