Lodash 源码阅读-baseAt
概述
baseAt
是 Lodash 内部的基础函数,用来批量获取对象中多个路径的值,并把这些值组成一个新数组返回。
前置学习
依赖函数
get
:安全地获取对象指定路径的值,即使中间路径不存在也不会报错
技术知识
- 数组操作:创建和填充数组的方法
- while 循环:使用前置递增运算符的循环写法
- 短路检查 :使用
object == null
同时检查null
和undefined
- 三元运算符:简化条件逻辑的表达方式
源码实现
javascript
/**
* The base implementation of `at` without support for individual paths.
*
* @private
* @param {Object} object The object to iterate over.
* @param {string[]} paths The property paths of elements to pick.
* @returns {Array} Returns the picked elements.
*/
function baseAt(object, paths) {
var index = -1,
length = paths.length,
result = Array(length),
skip = object == null;
while (++index < length) {
result[index] = skip ? undefined : get(object, paths[index]);
}
return result;
}
export default baseAt;
实现思路
baseAt
函数接收一个对象和一组路径数组,然后遍历所有路径,从对象中提取每个路径对应的值。如果对象为空(null 或 undefined),则会跳过实际获取过程,直接用 undefined 填充结果数组。函数通过一次遍历就完成了所有路径的值获取,最后返回这些值组成的新数组。
源码解析
javascript
function baseAt(object, paths) {
// 初始化变量
var index = -1, // 循环索引,从-1开始是为了配合前置++运算符
length = paths.length, // 路径数组长度
result = Array(length), // 预分配结果数组空间,提高性能
skip = object == null; // 判断对象是否为null或undefined
}
while (++index < length) {
result[index] = skip ? undefined : get(object, paths[index]);
}
这段代码初始化了函数需要的变量:
index
设为 -1,配合后面循环中的前置++
操作length
保存路径数组的长度result
预创建了一个指定长度的数组,比动态扩容更高效skip
标记对象是否为 null 或 undefined
javascript
while (++index < length) {
result[index] = skip ? undefined : get(object, paths[index]);
}
这是函数的核心循环:
- 使用前置
++
操作将index
递增,同时作为循环条件的一部分 - 对于每个路径,使用三元运算符决定结果:
- 如果
skip
为 true(对象为 null 或 undefined),直接填入 undefined - 否则调用
get(object, paths[index])
获取对应路径的值
- 如果
- 这种方式避免了在对象为空时多次调用
get
函数,是一种性能优化
javascript
return result;
}
最后返回填充完毕的结果数组。
关键点分析
-
性能优化:
- 使用
Array(length)
预分配数组空间而不是用push
动态增长 - 使用
skip
标记避免在对象为空时多次调用get
函数
- 使用
-
安全性:
- 通过
get
函数安全地获取嵌套属性,不会因为路径不存在而报错 - 对象本身为 null/undefined 时的特殊处理
- 通过
-
代码简洁:
- 使用三元运算符简化条件逻辑
- 整个函数主体只有一个简单的循环
应用示例
javascript
// 示例对象
const obj = {
user: {
name: "John",
profile: {
age: 28,
address: {
city: "New York",
},
},
},
posts: [
{ id: 1, title: "Hello" },
{ id: 2, title: "World" },
],
};
// 获取多个路径的值
baseAt(obj, [
"user.name",
"user.profile.age",
"posts[0].title",
"missing.path",
]);
// => ['John', 28, 'Hello', undefined]
// 对象为null的情况
baseAt(null, ["a", "b", "c"]);
// => [undefined, undefined, undefined]
总结
baseAt
函数是 Lodash 中 _.at
方法的核心实现,它通过巧妙的方式实现了批量获取对象属性的功能。函数设计简单高效,通过预分配结果数组和条件跳过来优化性能,同时依靠 get
函数确保了属性访问的安全性。这个函数体现了 Lodash 中对性能和健壮性的平衡考虑,既快速又可靠。