• JavaScript 中的纯函数


    前言

    纯函数 是一个常见的概念,在日常工作中也经常会遇到,它其实非常简单,今天我们来了解一下它的好处以及为什么要使用它。

    两个特点

    一个函数,如果符合以下两个特点,那么它就可以称之为 纯函数

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

    相同输入得到相同输出

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

    let greeting = 'Hello'
    
    function greet (name) {
      return greeting + ' ' + name
    }
    
    console.log(greet('World')) // Hello World

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

    那我们做以下修改:

    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 出来:

    const user = {
      username: 'savokiss'
    }
    
    function validate (user) {
      return user.username.length > 4;
    }
    
    const isValid = validate(user)

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

    电脑刺绣绣花厂 http://www.szhdn.com 广州品牌设计公司https://www.houdianzi.com

    为什么要用纯函数?

    你可能听过 纯函数 有不少优点,如果你经手过各种难维护的函数,你就更应该考虑使用 纯函数。

    可测试性(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)

    由于纯函数是自给自足的,它需要的东西都在输入参数中已经声明,所以它可以任意移植到任何地方。

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

  • 相关阅读:
    C语言 · 最小公倍数
    SSH实战 · SSH项目开发环境搭建
    C语言 · 回文数
    C语言 · 特殊回文数
    C语言 · 查找整数
    SSH实战 · SSH项目中怎么玩验证码
    SSH实战 · JAVA发送邮件相关
    SSH实战 · AJAX异步校验
    C语言 · 打印1-200之间的素数
    Jenkins权限设计错误解决办法
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13859099.html
Copyright © 2020-2023  润新知