Lodash 源码阅读-zip
概述
zip
函数用于将多个数组按照位置重组成新的分组数组,第一个分组包含各数组的第一个元素,第二个分组包含各数组的第二个元素,依此类推。它实现了矩阵转置操作,是 unzip
函数的逆操作。通过 baseRest
高阶函数实现了参数收集和处理,时间复杂度为 O(m×n),其中 m 是数组个数,n 是最长数组的长度。
前置学习
依赖函数
- unzip: 接收一个二维数组,实现矩阵转置(行列互换),返回新的二维数组
- baseRest: 创建一个接收不定数量参数的函数,将超出指定位置的参数收集到一个数组中
- identity: 返回第一个参数的函数,用作默认的转换函数
技术知识
- 函数式编程: 高阶函数的使用(函数作为参数和返回值)及不可变数据处理
- 函数组合: 通过嵌套函数调用实现功能组合,创建更复杂的函数行为
- 参数收集与扩展: JavaScript 中处理可变参数的技术,ES5 环境下模拟 ES6 rest 参数
- 矩阵转置算法: 二维数组的行列互换操作,常用于数据重组和表格数据处理
源码实现
var zip = baseRest(unzip);
实现思路
zip
函数的实现体现了函数式编程中优雅的函数组合思想。它通过高阶函数 baseRest
将 unzip
转化为一个接收多个数组参数的新函数,从而实现了参数收集和处理的功能转换。
源码解析
1. 函数设计与组合
var zip = baseRest(unzip);
这行代码展示了函数组合的精髓,将 unzip
函数通过 baseRest
进行包装,使其能够接受多个参数而非单个数组参数。baseRest
的作用是创建一个新函数,该函数:
- 接收任意数量的参数
- 将这些参数收集到一个数组中
- 将该数组传递给原始函数(这里是
unzip
)处理
这种设计使得 zip
和 unzip
形成了一对互补操作,同时保持了接口的一致性和灵活性。
2. 执行流程与数据转换
当调用 zip(['a', 'b'], [1, 2], [true, false])
时,执行流程如下:
baseRest
创建的包装函数收集所有参数:['a', 'b']
,[1, 2]
,[true, false]
- 这些参数被组合成数组:
[['a', 'b'], [1, 2], [true, false]]
- 该数组被传递给
unzip
函数 unzip
执行矩阵转置操作,返回[['a', 1, true], ['b', 2, false]]
unzip
的核心逻辑是查找所有数组中的最大长度,然后按索引位置进行重组。通过复用 unzip
的实现,既避免了代码重复,也保证了功能的一致性。
总结
- 利用高阶函数实现函数参数的动态收集与变换,一行代码实现复杂的数组转置功能
- 运用函数组合设计模式,通过包装现有函数创建新功能,体现代码复用的最佳实践
- 通过复用
unzip
函数避免重复实现,体现 DRY 原则,降低维护成本