Lodash源码阅读-baseRest

Lodash 源码阅读-baseRest

概述

baseRest 是 Lodash 内部工具函数,用于模拟 ES6 的剩余参数功能。它通过组合 overRestsetToString 两个函数,创建一个能处理不定数量参数的新函数,并保留原函数的字符串表示。这在实现柯里化和函数部分应用中非常有用。

前置学习

依赖函数

  • overRest:处理剩余参数的核心函数
  • setToString:保持函数的 toString 方法,便于调试
  • identity :返回输入值本身的函数,即 x => x

源码实现

js 复制代码
function baseRest(func, start) {
  return setToString(overRest(func, start, identity), func + "");
}

实现思路

baseRest 函数虽然只有一行代码,但实现了两个关键功能:

  1. 使用 overRest 创建一个能处理剩余参数的新函数
  2. 使用 setToString 保留原函数的字符串表示

为什么这样做?因为在 JavaScript 中,函数的 toString() 方法会返回函数的源代码,这对调试和函数识别很有用。当使用高阶函数时,新函数默认的 toString() 不会反映原函数的信息,所以需要专门设置。

源码解析

函数签名:function baseRest(func, start)

  • func: 需要处理的原始函数
  • start: 从第几个参数开始算作"剩余参数"(索引从 0 开始)

实现解析:

js 复制代码
return setToString(overRest(func, start, identity), func + "");
  1. 使用 overRest 创建处理剩余参数的新函数
  2. identity 保持剩余参数原样不变
  3. setToString 保留原函数的字符串表示

参数处理核心原理

当使用 baseRest 创建的函数被调用时,参数处理过程如下:

js 复制代码
// 创建一个包装函数
const wrapper = baseRest(function (first, rest) {
  console.log(first); // 10
  console.log(rest); // [20, 30, 40]
  return first + rest.reduce((sum, n) => sum + n, 0);
}, 1);

// 调用包装函数
wrapper(10, 20, 30, 40); // 结果: 100

处理流程:

  1. 参数分割:

    • 固定参数:[10](索引 0 之前的参数)
    • 剩余参数:[20, 30, 40](索引 1 及之后的参数)
  2. 调用准备:

    • 对剩余参数应用 identity 函数(保持不变)
    • 形成调用数组 otherArgs = [10, [20, 30, 40]]
  3. 函数调用:

    • 通过 apply(func, this, otherArgs) 调用
    • 相当于 func(10, [20, 30, 40])
    • 形参 first 接收第一个参数 10
    • 形参 rest 接收第二个参数 [20, 30, 40]

应用场景示例

1. 求和函数

js 复制代码
const sum = baseRest(function (first, rest) {
  return rest.reduce((total, num) => total + num, first);
}, 1);

sum(10, 20, 30, 40); // => 100

2. 数据库查询构建器

js 复制代码
const query = baseRest(function (table, conditions) {
  return `SELECT * FROM ${table} WHERE ${conditions.join(" AND ")}`;
}, 1);

query("users", "age > 18", "status = 'active'");
// => "SELECT * FROM users WHERE age > 18 AND status = 'active'"

3. 事件处理器

js 复制代码
const createEventHandler = baseRest(function (eventName, listeners) {
  return function (data) {
    console.log(
      `事件「${eventName}」触发,共有 ${listeners.length} 个处理函数`
    );
    listeners.forEach((listener) => listener(data));
  };
}, 1);

const clickHandler = createEventHandler(
  "点击",
  (data) => console.log("处理器1:", data),
  (data) => console.log("处理器2:", data)
);

clickHandler({ x: 100, y: 200 });

总结

baseRest 主要解决两个问题:

  1. 参数处理:在 ES6 之前环境中模拟剩余参数功能
  2. 元数据保留:保持原函数的字符串表示

即使在现代 JavaScript 已有原生剩余参数的情况下,baseRest 在实现函数式编程模式、处理兼容性和创建高级函数工具时仍然非常有价值。

相关推荐
JarvanMo3 分钟前
如何在Flutter中保护密钥文件?
前端·flutter
Mike_jia13 分钟前
一篇文章带你了解一款强大的企业家监控系统---Zabbix
前端
七月丶14 分钟前
🚀 从 Git 操作痛点出发,我为什么开发了 gix?
前端·后端·github
Mike_jia14 分钟前
Cabot监控系统全解析:自建企业级监控的终极方案
前端
至尊童19 分钟前
7个冷门JavaScript技巧
javascript
北京_宏哥20 分钟前
🔥吐血整理Bolt.diy 部署与应用攻略
前端·人工智能·openai
Muxxi23 分钟前
判断页面滚动方向的方法
javascript
毕欧外24 分钟前
vue
前端
bnnnnnnnn25 分钟前
Nuxt 官网在 4K 屏幕上字体太小?我用 postcss-pxtorem + 根字体动态设置完美解决!
前端·postcss
小钰能吃三碗饭25 分钟前
第十二篇:【React + AI】深度实践:从 LLM 集成到智能 UI 构建
前端·react.js·aigc