Lodash 源码阅读-arrayMap
概述
arrayMap
是 Lodash 中的一个内部工具函数,专门用于对数组进行映射操作。它是 _.map
函数在处理数组类型时的底层实现,提供了高效的数组元素转换功能。
前置学习
- Array 构造函数:了解 JavaScript 中如何预分配指定长度的数组
- 数组遍历 :了解 JavaScript 中的循环遍历方法,特别是
while
循环 - 函数回调:理解如何将函数作为参数传递并在循环中调用
源码实现
js
function arrayMap(array, iteratee) {
var index = -1,
length = array == null ? 0 : array.length,
result = Array(length);
while (++index < length) {
result[index] = iteratee(array[index], index, array);
}
return result;
}
实现思路
arrayMap
函数的实现非常直接明了:它接收一个数组和一个迭代函数作为参数,然后遍历数组中的每个元素,对每个元素应用迭代函数,并将结果存储在一个新数组中。最后返回这个新数组。
这个函数是 _.map
的专用版本,专门针对数组类型进行了优化,不支持 Lodash 中常见的迭代器简写形式(如字符串路径、对象等)。
源码解析
1. 参数处理和初始化
js
var index = -1,
length = array == null ? 0 : array.length,
result = Array(length);
这部分代码完成了三个初始化操作:
- 初始化索引 :将
index
设置为 -1,为后续的++index
操作做准备 - 获取数组长度 :检查
array
是否为null
或undefined
,如果是则长度为 0,否则获取其length
属性 - 创建结果数组 :使用
Array(length)
预分配一个与输入数组相同长度的新数组
这里使用 array == null
而不是 array === null || array === undefined
是一种简洁的写法,因为在 JavaScript 中,null == undefined
为 true
。
预分配结果数组的长度是一种优化手段,避免了在循环过程中动态扩展数组带来的性能开销。
2. 数组遍历和映射
js
while (++index < length) {
result[index] = iteratee(array[index], index, array);
}
这部分代码使用 while
循环遍历数组的每个元素:
++index < length
在每次循环开始时递增索引,并检查是否已遍历完所有元素- 对于每个元素,调用
iteratee
函数,传入三个参数:- 当前元素值:
array[index]
- 当前索引:
index
- 原始数组:
array
- 当前元素值:
- 将
iteratee
函数的返回值存储在结果数组的相应位置
这种实现方式保持了与 JavaScript 原生 Array.prototype.map()
方法相同的参数顺序和行为,使得函数易于理解和使用。
3. 返回结果
js
return result;
最后,函数返回包含所有映射结果的新数组。
应用场景
在 Lodash 中的作用
arrayMap
在 Lodash 中主要用于以下场景:
-
作为
_.map
函数的数组处理实现 :当_.map
检测到输入集合是数组时,会调用arrayMap
进行处理js// 在 _.map 函数中的使用 function map(collection, iteratee) { var func = isArray(collection) ? arrayMap : baseMap; return func(collection, getIteratee(iteratee, 3)); }
-
在其他 Lodash 函数中用于数组转换 :如
baseToPairs
等函数内部使用arrayMap
进行数组转换js// 在 baseToPairs 函数中的使用 function baseToPairs(object, props) { return arrayMap(props, function (key) { return [key, object[key]]; }); }
在前端开发中的应用
虽然我们很少直接使用 arrayMap
,但其实现思想在前端开发中有广泛应用:
-
数据转换:将一组数据转换为另一种格式,如将用户数据转换为视图模型
jsconst userViewModels = arrayMap(users, (user) => ({ displayName: `${user.firstName} ${user.lastName}`, avatarUrl: user.profilePicture || "default.png", isActive: user.status === "active", }));
-
DOM 操作:将数据数组转换为 DOM 元素数组
jsconst listItems = arrayMap(items, (item) => { const li = document.createElement("li"); li.textContent = item.name; return li; });
-
计算派生值:基于原始数据计算新的数据集
jsconst prices = arrayMap(products, (product) => product.price); const averagePrice = prices.reduce((sum, price) => sum + price, 0) / prices.length;
总结
arrayMap
函数是 Lodash 中一个简洁而高效的内部工具函数,它专门用于处理数组的映射操作。通过预分配结果数组和简单的循环实现,它提供了良好的性能和可靠的行为。
从设计角度看,arrayMap
函数体现了以下几点优秀的编程实践:
- 单一职责:函数只专注于数组映射这一任务,不处理其他类型的集合
- 性能优化:通过预分配结果数组长度,避免了动态扩展数组的开销
- 健壮性 :正确处理了
null
和undefined
输入的情况 - 一致性 :保持了与 JavaScript 原生
Array.prototype.map()
相同的参数顺序和行为
这种专门化的设计使得 Lodash 能够在处理不同类型的集合时选择最优的实现方式,既保证了功能的完整性,又兼顾了性能的优化。