JavaScript中功能管道的简单说明

有时候我被问到为什么我们不再在RxJS中使用“点链”,或者为什么RxJS转向使用 。有很多原因,但这确实需要从更高层次上看待RxJS。

对管道功能的需求来自两个问题:希望为简单类型(如Array,Observable,Promise等)提供广泛的可用开发API,以及希望发布更小的应用程序。

尺寸问题

JavaScript是一种非常独特的语言,存在大多数其他编程语言所没有的问题:通常,JavaScript通过网络发布,解析并在用户想要使用JavaScript正在启动的应用程序的时刻执行。 JavaScript发送的越多,下载和解析所需的时间就越长,从而降低了应用的响应速度。可能对用户体验产生巨大影响的东西。

这意味着尝试保持JavaScript应用程序的小巧至关重要。幸运的是,我们现在有很多很棒的工具可以做到这一点。我们有很多“构建时”的捆绑器和优化器,它们可以执行诸如树摇动之类的事情,以便在构建时删除未使用的代码,因此我们可以向用户发送尽可能少的JavaScript。

不幸的是,如果不能静态地确保代码没有在某处使用,那么树抖动不会删除代码。

提供广泛的API

为了使类型尽可能有用,最好将一组结合良好的已知功能附加到该类型上。特别是通过在该类型上从左到右进行调用可以“链接”它。

JavaScript为内容提供广泛API的“内置”方式是原型扩充。这意味着您可以为任何给定类型添加方法 原型 宾语。所以如果我们想添加一个自定义 可能性 过滤到数组,我们可以这样做:

排列原型可能性 = 功能() {   返回 这个过滤X => X  2 === 1 }  排列原型 = 功能 () {   返回 这个地图X => X + X); }  排列原型日志 = 功能 () {   这个的forEachX => 安慰日志X));   返回 这个; } 

原型增强是有问题的

变异全局变量。你现在正在操纵别人可以触摸的东西。这意味着其他代码可以依赖于此开始 可能性 正在进行的方法 排列,不知道它实际上来自第三方。这也意味着另一部分代码可以通过并践踏 可能性 用它自己的定义 可能性。有这样的解决方案,比如使用 符号,但它仍然不理想。

原型方法不能动摇。 Bundlers目前不会尝试删除已修补到原型上的未使用方法。有关推理,请参阅上文。捆绑者无法知道第三方是否依赖于使用该原型方法。

功能编程FTW

一旦你意识到了 这个 上下文实际上只是将另一个参数传递给函数的一种奇特方式,你意识到你可以像这样重写上面的方法:

功能 可能性排列 {   返回 排列过滤X => X  2 === 0); }  功能 排列 {   返回 ARR地图X => X + X); }  功能 日志排列 {   排列的forEachX => 安慰日志X));   返回 排列; } 

现在的问题是你必须从右到左阅读你的阵列发生的事情,而不是从左到右:

//哎 日志可能性((1 2 3 4 )))) 

但是,优点是,如果我们不使用 ,比方说,一个捆绑者将能够树摇动并删除 功能从最终结果发送给用户,使您的应用程序更小,更快。

管道从左到右的可读性

为了获得更好的从左到右的可读性,我们可以使用a 功能。这是一个常见的功能模式,可以通过一个简单的功能来完成:

function pipe(... fns){return(arg)=> fns.reduce((prev,fn)=> fn(prev),arg); } 

这样做是返回一个新的高阶函数,它接受一个参数。返回的函数将参数传递给函数列表中的第一个函数, FNS,然后获取结果,并将其传递给列表中的下一个函数,依此类推。

这意味着我们现在可以从左到右组合这些东西,这更具可读性:

可能性  日志)((1 2 3 4 )) 

您还可以创建一个帮助程序,允许您将参数作为第一个参数提供,以使其更具可读性(如果可重用性更低),如下所示:

功能 pipeWithARG ...FNS {   返回 (...FNS)(ARG); }  pipeWith((1 2 3 4  可能性  日志); 

如果是 pipeWith现在它将采用第一个参数,并将其传递给参数列表中紧跟其后的函数,然后它将获取结果并将其传递给参数列表中的下一个函数,依此类推。

带有参数的“可管理”函数

要创建一个可以通过管道输入但具有参数的函数,只需更高阶函数即可。例如,如果我们想制作一个 乘以 功能而不是

pipeWith((1 2 3 4  可能性 乘以2 日志);  功能 乘以X {   返回 排列 => 排列地图ñ => ñ * X); } 

组成

因为它只是函数,所以您可以使用简化代码并使其更具可读性 创建其他可重用,可管理的功能

常量 tripleTheOdds = 可能性 乘以3));   pipeWith((1 2 3 4  tripleTheOdds 日志 

更大的JS生态系统和管道运营商

这与RxJS运营商通过Observable使用的模式大致相同 方法。这样做是为了解决上面原型中列出的所有问题。但这显然适用于任何类型。

原型 扩充可能是在JavaScript中向类型添加方法的“祝福”方式,在我看来,它有点像反模式。 JavaScript需要更多地开始接受这种模式,理想情况下,我们可以获得一个简单版本的管道运算符提议,以便在JavaScript中着陆。

使用管道运算符,上面的代码可能看起来像这样,但在功能上是相同的,并且不需要声明 帮手。

pipeWith((1 2 3 4  可能性  日志);  //变得  1 2 3 4  |> 可能性 |>  |> 日志 

资讯来源:由0x资讯编译自DEV,原文:https://dev.to/benlesh/a-simple-explanation-of-functional-pipe-in-javascript-2hbj ,版权归作者所有,未经许可,不得转载
你可能还喜欢