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 在实现函数式编程模式、处理兼容性和创建高级函数工具时仍然非常有价值。

相关推荐
HashTang14 分钟前
不用再配服务器了!这套 Next.js + Cloudflare 模板,一个人搞定全栈出海
前端·后端·边缘计算
Cory.眼27 分钟前
WebRTC入门指南:实时通信零基础
javascript·webrtc·实时通信
前端架构师-老李1 小时前
16 Electron 应用自动更新方案:electron-updater 完整指南
前端·javascript·electron
一只学java的小汉堡1 小时前
HTML 01入门:从概念到开发环境搭建与页面头部配置
前端·css·html
拖拉斯旋风1 小时前
📚 JavaScript 变量声明三剑客:`var`、`let`、`const` 学习笔记
javascript
用户21496515898751 小时前
从零搭建uniapp环境-记录
前端
可触的未来,发芽的智生3 小时前
追根索源:换不同的词嵌入(词向量生成方式不同,但词与词关系接近),会出现什么结果?
javascript·人工智能·python·神经网络·自然语言处理
努力写代码的熊大3 小时前
stack、queue与priority_queue的用法解析与模拟实现
java·前端·javascript
im_AMBER3 小时前
React 06
前端·javascript·笔记·学习·react.js·前端框架
wyzqhhhh4 小时前
前端常见的设计模式
前端·设计模式