Lodash源码阅读-baseAt

Lodash 源码阅读-baseAt

概述

baseAt 是 Lodash 内部的基础函数,用来批量获取对象中多个路径的值,并把这些值组成一个新数组返回。

前置学习

依赖函数

  • get:安全地获取对象指定路径的值,即使中间路径不存在也不会报错

技术知识

  • 数组操作:创建和填充数组的方法
  • while 循环:使用前置递增运算符的循环写法
  • 短路检查 :使用 object == null 同时检查 nullundefined
  • 三元运算符:简化条件逻辑的表达方式

源码实现

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;
}

最后返回填充完毕的结果数组。

关键点分析

  1. 性能优化

    • 使用 Array(length) 预分配数组空间而不是用 push 动态增长
    • 使用 skip 标记避免在对象为空时多次调用 get 函数
  2. 安全性

    • 通过 get 函数安全地获取嵌套属性,不会因为路径不存在而报错
    • 对象本身为 null/undefined 时的特殊处理
  3. 代码简洁

    • 使用三元运算符简化条件逻辑
    • 整个函数主体只有一个简单的循环

应用示例

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 中对性能和健壮性的平衡考虑,既快速又可靠。

相关推荐
知识分享小能手几秒前
Vue3 学习教程,从入门到精通,Vue3 中使用 Axios 进行 Ajax 请求的语法知识点与案例代码(23)
前端·javascript·vue.js·学习·ajax·vue·vue3
一大树几秒前
首屏白屏的处理方案~嗖得一下
前端
小old弟2 分钟前
🤔同时发送100个请求?!手撕,并发请求⌨️
前端
533_7 分钟前
[echarts] 更新数据
前端·javascript·echarts
excel7 分钟前
理解 JavaScript 中的迭代器协议与中断行为:for...of vs for...in
前端
幻雨様9 分钟前
UE5多人MOBA+GAS 番外篇:同时造成多种类型伤害,以各种属性值的百分比来应用伤害(版本二)
java·前端·ue5
讨厌吃蛋黄酥14 分钟前
利用Mock实现前后端联调的解决方案
前端·javascript·后端
zzywxc78735 分钟前
在处理大数据列表渲染时,React 虚拟列表是提升性能的关键技术,但在实际实现中常遇到渲染抖动和滚动定位偏移等问题。
前端·javascript·人工智能·深度学习·react.js·重构·ecmascript
Hello.Reader1 小时前
Rust → WebAssembly 的性能剖析全指南
前端·rust·wasm
前端小巷子1 小时前
Vue 2 Diff 算法
前端·vue.js·面试