什么是管道?
管道操作符是操作系统中常用的处理数据的方法,属于软件架构风格中的管道过滤器风格,原理是将前一个节点的输出作为下一个节点的输入,每个节点只针对输入进行处理。
目前现有的JavaScript语言针对可枚举类型实现了链式调用,或者将值传递给函数,实现类似效果,如a(b(c([]))),但这这种效果是基于函数嵌套实现的,如果有多个方法,则函数嵌套层级会变的更深,降低了代码的可读性提高了代码的维护难度。
针对链式调用的一个前提是必须指定一个对象,通过对象将各个函数串在一起,实现构建,这也是设计模式中的建造者模式。
那么为什么会出现管道运算模式呢?
目的是为了提高代码的可读性和流畅性,如果我们使用管道符号,就可以脱离上述的两种方式,实现不同函数之间仅仅关注自身的输入和输出,而无需关系代码的整体组织,将其交给管道符号,使其能够提升函数的灵活性,同时管道概念本身也是如此,在GNU Linux操作系统中,不同的命名通常可以使用管道符号进行联合使用,而每个命令也只是符合操作系统的标准输入输出,命令只针对自己需要的函数进行处理即可,通过管道运算符完成复杂逻辑处理。
同时管道运算也大大简化了临时变量的声明和使用。
@babel/plugin-proposal-pipeline-operator的配置
proposal有四种配置,分别是 hach,fsharp,minial,smart
hackhack管道,可使用多元函数(多参数函数)fsharp带 await 的F#管道,用于一元函数的调用(单参数函数)minimal最小F#样式管道smart智能混合管道,已经弃用
目前 hack和fsharp都是比较重要的,fsharp是通过单参数来隐式接受传入的变量,更加符合传统意义上的管道模式,而hack则可以利用传出的对象的指定函数直接处理,更加灵活
配置使用环境
{
"devDependencies": {
"@babel/cli": "^7.23.4",
"@babel/core": "^7.23.6",
"@babel/preset-env": "^7.23.6",
"@babel/plugin-proposal-pipeline-operator": "^7.23.3" // babel的TC39管道实现
}
}
## babel配置
```json
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "14"
}
}
]
],
"plugins": [
["@babel/plugin-proposal-pipeline-operator", { "topicToken": "^^" ,"proposal":"hack"}] // 设置占位符为 ^^, 模式为 hack模式
]
}
测试代码
[1,2,3,4,5,6,7]
.map(envar => envar)
|> ^^.map(item=> item + 'pipeline')
|> ^^.join()
|> console.log(^^) // 1pipeline,2pipeline,3pipeline,4pipeline,5pipeline,6pipeline,7pipeline
经过babel编译后,代码变成了通过map的形式进行连接处理
"use strict";
var _ref, _ref2;
_ref2 = [1, 2, 3, 4, 5, 6, 7].map(envar => envar).map(item => item + 'pipeline').join(), (_ref = console.log(_ref2), console.log(_ref + 'stage'));
如果我们自定义函数进行处理,代码如下
function mixinTitle(str){
return str.map(item=>item+'title')
}
[1,2,3,4,5,6,7]
.map(envar => envar)
|> mixinTitle(^^)
|> mixinTitle(^^)
|> mixinTitle(^^)
|> mixinTitle(^^)
|> mixinTitle(^^)
|> ^^.join()
|> console.log(^^)
最终经过babel编译后的代码生成如下形式,我们可以看到,babel最终会将自定义函数处理成嵌套格式,实现该效果
"use strict";
var _ref;
function mixinTitle(str) {
return str.map(item => item + 'title');
}
_ref = mixinTitle(mixinTitle(mixinTitle(mixinTitle(mixinTitle([1, 2, 3, 4, 5, 6, 7].map(envar => envar)))))).join(), console.log(_ref);
如果使用f#的方式直接调用一元函数,则书写格式如下,每个函数块只接受一个参数
function mixinTitle(str){
return str.map(item=>item+'title')
}
function join(arr) {
return arr.join()
}
[1,2,3,4,5,6,7]
.map(envar => envar)
|> mixinTitle
|> mixinTitle
|> mixinTitle
|> mixinTitle
|> mixinTitle
|> join
|> console.log
经过babel编译后的代码格式如下
生成的逻辑代码包含了很多临时变量
"use strict";
var _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _map;
function mixinTitle(str) {
return str.map(item => item + 'title');
}
function join(arr) {
return arr.join();
}
_ref = (_ref2 = (_ref3 = (_ref4 = (_ref5 = (_ref6 = (_map = [1, 2, 3, 4, 5, 6, 7].map(envar => envar), mixinTitle(_map)), mixinTitle(_ref6)), mixinTitle(_ref5)), mixinTitle(_ref4)), mixinTitle(_ref3)), join(_ref2)), console.log(_ref);