• JavaScript中的管道运算符
  • 发布于 15小时前
  • 9 热度
    0 评论
当你的代码库还很小的时候,一切都清清楚楚、直来直去。可一旦项目膨胀,函数像藤蔓一样彼此勾连,层层嵌套把本来简单的逻辑搅成一锅粥。这时函数式编程就开始显神通了。我最初入门时靠的是一个优雅的小工具——compose。它把混乱的嵌套调用改造成有序的变换序列,看起来就顺眼多了。而现在,我们无需再额外写工具,也能做到同样甚至更清晰的表达。

你不再把函数一层层包起来,而是用一个简单的运算符从左到右把它们串起来。先上手,再解释。

把“套娃式”调用拉平成管道
在 ES2025 中,有一个被提案的运算符,用来把嵌套且凌乱的函数调用改写成直观易读的流水线。它能把那些“里三层外三层”的表达拆解成一条人人都能跟得上的数据管道。目前它处于 TC39 Stage 2,意味着正在积极推进,但尚不适合直接用于生产。管道运算符(|>)允许你从左到右串联操作,而不是传统的“从最里层往外读”。把它想成数据的传送带:每一步拿到上一步的结果,继续变换。
// 现在的写法——嵌套调用
const result = h(g(f(x)));
// 堆代码 duidaima.com
// 使用管道运算符
const result = x |> f |> g |> h;
它的精妙之处在于占位符机制:用一个特殊的占位符,精确标注“上一步的值应该放到哪里”。
// 传统嵌套(读起来费劲)
const result = formatCurrency(
  calculateTax(
    applyDiscount(getPrice(product), 10),
    0.08
  )
);

// 管道 + 占位符(清楚、线性)
const result = product
  |> getPrice(%)
  |> applyDiscount(%, 10)
  |> calculateTax(%, 0.08)
  |> formatCurrency(%);
有了占位符,你就能精准控制数据的落点。正是占位符把管道运算符从“锦上添花”推到了“不可或缺”。
const data = users
  |> %.filter(u => u.active)
  |> %.map(u => u.name)
  |> { count: %.length, names: % }
  |> JSON.stringify(%, null, 2);
示例 1:API 数据处理
// 之前:层层嵌套,读写都吃力
const processUserData = (response) => {
  return response.users
    .map(user => ({
      ...user,
      fullName: formatName(user.firstName, user.lastName),
      isActive: checkStatus(user.status, 'active')
    }))
    .filter(user => user.isActive)
    .sort((a, b) => a.fullName.localeCompare(b.fullName));
};

// 之后:清晰的管道
const processUserData = (response) => {
  return response.users
    |> %.map(user => ({
         ...user,
         fullName: formatName(user.firstName, user.lastName),
         isActive: checkStatus(user.status, 'active')
       }))
    |> %.filter(user => user.isActive)
    |> %.sort((a, b) => a.fullName.localeCompare(b.fullName));
};
示例 2:表单校验流水线
const validateForm = (formData) => {
  return formData
    |> sanitizeInput(%)
    |> validateRequired(%, ['email', 'password'])
    |> validateEmail(%.email) ? % : { ...%, errors: [...%.errors, 'Invalid email'] }
    |> validatePassword(%.password) ? % : { ...%, errors: [...%.errors, 'Weak password'] }
    |> %.errors.length === 0
         ? { valid: true, data: % }
         : { valid: false, errors: %.errors };
};
示例 3:字符串处理链
// 把用户输入变成 URL slug
const createSlug = (title) => {
  return title
    |> %.toLowerCase()
    |> %.trim()
    |> %.replace(/[^\w\s-]/g, '')
    |> %.replace(/\s+/g, '-')
    |> %.substring(0, 50)
    |> %.replace(/-+$/, '');
};
注意到没有?占位符 % 让你可以直接在管道值上调用方法。这份灵活性正是我们一直缺少的。

如何在项目里先用起来
虽然管道运算符还停留在 Stage 2,但你可以通过 Babel 7.15+ 先行体验。
安装 Babel 插件:
npm install --save-dev @babel/plugin-proposal-pipeline-operator
配置 .babelrc:
{
  "plugins": [
    [
      "@babel/plugin-proposal-pipeline-operator",
      {
        "proposal": "hack",
        "topicToken": "%"
      }
    ]
  ]
}
完成后,你就可以愉快地写管道代码,由 Babel 将其转译为当前浏览器可执行的形式。我已经在生产中以转译方式使用了数月,产物干净、性能稳定。
用户评论