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

相关推荐
小二·5 小时前
Python Web 开发进阶实战 :AI 原生数字孪生 —— 在 Flask + Three.js 中构建物理世界实时仿真与优化平台
前端·人工智能·python
Whisper_Sy6 小时前
Flutter for OpenHarmony移动数据使用监管助手App实战 - 网络状态实现
android·java·开发语言·javascript·网络·flutter·php
新缸中之脑6 小时前
Weave.js:开源实时白板库
开发语言·javascript·开源
Amumu121386 小时前
Vue组件化编程
前端·javascript·vue.js
We་ct6 小时前
LeetCode 6. Z 字形变换:两种解法深度解析与优化
前端·算法·leetcode·typescript
小二·7 小时前
Python Web 开发进阶实战(终章):从单体应用到 AI 原生生态 —— 45 篇技术演进全景与未来开发者生存指南
前端·人工智能·python
m0_637256588 小时前
vue-baidu-map添加了类型组件导致非常卡顿的问题
前端·javascript·vue.js
雨季6668 小时前
基于设备特征的响应式 UI 构建:Flutter for OpenHarmony 中的智能布局实践
javascript·flutter·ui
挂机且五杀8 小时前
为什么在React地图组件里,memo 不是优化,而是生存?
前端·react.js·前端框架
RFCEO8 小时前
HTML编程 课程七、:HTML5 新增表单标签与属性
前端·html·html5·搜索框·手机号·邮箱验证·日期选择