当前位置: 首页 > Web前端 > HTML5

FP浅析:JavaScript中的纯函数

时间:2023-04-05 01:01:30 HTML5

前言纯函数是一个比较常见的概念,在日常工作中经常会遇到。其实很简单。今天我们将了解它的好处以及我们应该使用它的原因。两个特征一个函数如果满足以下两个特征就可以称为纯函数:对于相同的输入,总是会得到相同的输出,没有任何可观察到的副作用。我们先来看一个。不纯的相反典型:letgreeting='Hello'functiongreet(name){returngreeting+''+name}console.log(greet('World'))//在上面的代码中HelloWorld,greet('World'),它总是返回HelloWorld吗?显然不是,如果我们修改了greeting的值,就会影响greet函数的输出。也就是说,函数greet实际上依赖于外部状态。然后我们做如下修改:functiongreet(greeting,name){returngreeting+''+name}console.log(greet('Hi','Savo'))//HiSavo也传入了greeting参数,所以for任何输入参数都有一个对应的唯一输出参数,这个函数符合第一个特性。无副作用副作用是指该函数的运行不会修改外部状态。我们来看典型的否定:constuser={username:'savokiss'}letisValid=falsefunctionvalidate(user){if(user.username.length>4){isValid=true}}可以看出,当函数被执行时,它会被修改为isValid(注意:如果你的函数没有返回任何值,它可能有副作用!)那么我们如何去除这个副作用呢?其实不需要修改外部isValid变量,我们只需要在函数中返回校验结果即可:constuser={username:'savokiss'}functionvalidate(user){returnuser.username.length>4;}constisValid=validate(user)这样validate函数就不会修改任何外部状态~为什么要用纯函数呢?您可能听说过纯函数有很多优点。如果你经历过各种难以维护的函数,你应该考虑使用纯函数。可测试的(Testable)让我们先使用不纯的greet方法来做单元测试://jestsyntaxdescribe('greet',function(){it('showsagreeting',function(){expect(greet('Savo')).toEqual('你好萨沃')});});如果我们将greeting变量改为Hi,上面的测试就会失败,这在自然界中是不应该发生的。那么如果我们换成纯函数版的greet,一切就那么自然了~只要修改单元测试传递的参数就可以了!可缓存(Cacheable)纯函数可以根据输入进行缓存。缓存是通过一种称为记忆的技术实现的。以下代码来自Vue源代码:/***创建一个纯函数的缓存版本。*只适用于缓存接收字符串作为参数的fn*/exportfunctioncached(fn){constcache=Object.create(null)returnfunctioncachedFn(str){consthit=cache[str]returnhit||(cache[str]=fn(str))}}/***将字符串大写。*/exportconstcapitalize=cached((str)=>{returnstr.charAt(0).toUpperCase()+str.slice(1)})capitalize是一个缓存函数。如果多次调用,它会返回缓存的值,从而节省计算资源。这一切的前提是,传入缓存的函数是纯函数。可移植性/自文档化(Portable/Self-Documenting)由于纯函数是自给自足的,它所需要的一切都已在输入参数中声明,因此可以任意移植到任何地方。而且纯函数老老实实对自己的依赖,看它的形参就知道了~俗话说形参好,注释不用~(双击!)纯函数就是这样的正直的小可爱~综上所述,我们对纯函数有了一个大概的认识,这对我们写出好的代码有很大的意义,也是函数式编程的精髓所在。本来这篇文章想简单的介绍一下纯函数,但是我记得没有提到柯里化(currying),所以下次有机会再说说柯里化吧~走着瞧吧!参考链接WhatisaPureFunctionJS函数式编程指南中文版