Lodash源码阅读-overRest

Lodash 源码阅读-overRest

概述

overRest 是 Lodash 内部的工具函数,它模拟了 ES6 的剩余参数功能,能将函数参数分成固定参数和剩余参数两部分,并对剩余参数进行转换处理。这是实现 Lodash 柯里化和部分应用的核心基础。

前置学习

依赖函数

  • nativeMax:原生 Math.max 的引用,获取两个数的最大值
  • apply:封装了 Function.prototype.apply 的函数调用工具

技术知识

  • 函数柯里化:将接收多个参数的函数转换为一系列接收单一参数的函数
  • 剩余参数 :ES6 的 ...args 语法的模拟实现
  • arguments 对象:类数组对象,包含调用函数时传入的所有参数
  • apply 方法:以指定的 this 值和参数数组调用函数

源码实现

js 复制代码
function overRest(func, start, transform) {
  start = nativeMax(start === undefined ? func.length - 1 : start, 0);
  return function () {
    var args = arguments,
      index = -1,
      length = nativeMax(args.length - start, 0),
      array = Array(length);

    while (++index < length) {
      array[index] = args[start + index];
    }
    index = -1;
    var otherArgs = Array(start + 1);
    while (++index < start) {
      otherArgs[index] = args[index];
    }
    otherArgs[start] = transform(array);
    return apply(func, this, otherArgs);
  };
}

实现思路

overRest 函数通过闭包实现参数的分割与转换:

  1. 确定分割位置:通过 start 参数决定哪些是固定参数,哪些是需要处理的剩余参数
  2. 收集和转换参数:将原始参数分为两组,对剩余参数应用转换函数
  3. 重组参数:将固定参数与转换后的剩余参数组合成新的参数数组
  4. 调用原函数:使用新的参数数组调用原始函数

源码解析

函数签名:

js 复制代码
function overRest(func, start, transform)
  • func: 需要处理的目标函数
  • start: 参数分割点的位置(默认为 func.length - 1)
  • transform: 用于处理剩余参数的转换函数

实现步骤解析:

  1. 确定分割位置

    js 复制代码
    start = nativeMax(start === undefined ? func.length - 1 : start, 0);

    这行代码确保 start 至少为 0,默认取函数的形参个数减 1。

    示例:如果 funcfunction(a, b, c) {},则 func.length 为 3,默认 start 为 2。

  2. 创建闭包函数:返回一个新函数,用于处理参数:

    js 复制代码
    return function () {
      // 函数实现
    };
  3. 收集剩余参数

    js 复制代码
    var args = arguments,
      index = -1,
      length = nativeMax(args.length - start, 0),
      array = Array(length);
    
    while (++index < length) {
      array[index] = args[start + index];
    }

    假设调用 function(1, 2, 3, 4, 5)start 为 2:

    • args[1, 2, 3, 4, 5]
    • length5 - 2 = 3
    • array 最终为 [3, 4, 5](剩余参数)
  4. 收集固定参数

    js 复制代码
    index = -1;
    var otherArgs = Array(start + 1);
    while (++index < start) {
      otherArgs[index] = args[index];
    }

    接续上例:

    • otherArgs 初始为长度为 3 的数组
    • 循环后变为 [1, 2, undefined](固定参数)
  5. 应用转换与调用

    js 复制代码
    otherArgs[start] = transform(array);
    return apply(func, this, otherArgs);
    • 如果 transformidentity(返回原值)函数,则 otherArgs 变为 [1, 2, [3, 4, 5]]
    • 最终调用 func(1, 2, [3, 4, 5])

总结

overRest 函数通过巧妙的参数处理机制,实现了以下几点技术亮点:

  1. 向后兼容性:在 ES6 之前的环境中模拟了剩余参数功能
  2. 参数转换灵活性 :通过 transform 参数提供了对剩余参数的自定义处理能力
  3. 函数式编程支持:为 Lodash 中的柯里化、偏函数应用等高阶函数提供了基础设施

从设计模式角度看,overRest 采用了函数式编程中的高阶函数模式,通过返回新函数的方式实现了对原函数的装饰和增强,体现了"不变性"和"组合性"的函数式编程理念。

相关推荐
未来之窗软件服务31 分钟前
打开所在文件路径,鸿蒙系统,苹果macos,windows,android,linux —智能编程—仙盟创梦IDE
前端·ide·资源管理器·仙盟创梦ide
houzhizhen1 小时前
SQL JOIN 关联条件和 where 条件的异同
前端·数据库·sql
^小桃冰茶5 小时前
CSS知识总结
前端·css
运维@小兵5 小时前
vue注册用户使用v-model实现数据双向绑定
javascript·vue.js·ecmascript
巴巴_羊6 小时前
yarn npm pnpm
前端·npm·node.js
chéng ௹7 小时前
vue2 上传pdf,拖拽盖章,下载图片
前端·css·pdf
嗯.~7 小时前
【无标题】如何在sheel中运行Spark
前端·javascript·c#
A_aspectJ10 小时前
【Bootstrap V4系列】学习入门教程之 组件-输入组(Input group)
前端·css·学习·bootstrap·html
兆。10 小时前
电子商城后台管理平台-Flask Vue项目开发
前端·vue.js·后端·python·flask
互联网搬砖老肖10 小时前
Web 架构之负载均衡全解析
前端·架构·负载均衡