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

相关推荐
li35743 小时前
将已有 Vue 项目通过 Electron 打包为桌面客户端的完整步骤
前端·vue.js·electron
Icoolkj4 小时前
VuePress 与 VitePress 深度对比:特性、差异与选型指南
前端·javascript·vue.js
excel4 小时前
CNN 分层详解:卷积、池化到全连接的作用与原理
前端
excel4 小时前
CNN 多层设计详解:从边缘到高级特征的逐层学习
前端
^Rocky5 小时前
JavaScript性能优化实战
开发语言·javascript·性能优化
西陵5 小时前
Nx带来极致的前端开发体验——任务编排
前端·javascript·架构
大前端helloworld6 小时前
从初中级如何迈入中高级-其实技术只是“入门卷”
前端·面试
笑鸿的学习笔记6 小时前
JavaScript笔记之JS 和 HTML5 的关系
javascript·笔记·html5
东风西巷7 小时前
Balabolka:免费高效的文字转语音软件
前端·人工智能·学习·语音识别·软件需求