Lodash源码阅读-property

Lodash 源码阅读-property

概述

property 是 Lodash 中的函数式编程工具,用来创建一个属性访问器函数。这个函数接收对象,返回对象指定路径上的属性值。它能够大大简化数据操作过程,特别是在处理复杂的对象集合时非常有用。

前置学习

依赖函数

  • isKey:判断传入的值是否为简单属性键(而非复杂路径)
  • toKey:将值转换为有效的对象属性键
  • baseProperty:基础函数,用于访问对象的单层属性
  • basePropertyDeep:基础函数,用于访问对象的深层嵌套属性

技术知识

  • 高阶函数:返回函数的函数,property 返回的是一个函数
  • 属性路径 :访问嵌套对象的路径表示,如 'user.profile.name'['user', 'profile', 'name']
  • 策略模式:根据输入类型选择不同的处理策略
  • 函数式编程:纯函数、无副作用、函数组合等理念

源码实现

javascript 复制代码
function property(path) {
  return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
}

实现思路

property 函数的实现非常简洁明了:

  1. 接收一个路径参数 path,可以是字符串、数组或符号
  2. 判断路径是否为简单属性键(使用 isKey 函数)
  3. 如果是简单属性键(如 'name'),使用 baseProperty 创建简单访问器
  4. 如果是复杂路径(如 'user.profile.name' 或数组),使用 basePropertyDeep 创建深层访问器
  5. 返回创建的访问器函数,该函数可以传入对象来获取属性值

这种分治策略根据路径的复杂度选择最优的实现方式,既保证了功能完整性,又考虑了性能优化。

源码解析

路径类型判断

javascript 复制代码
isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);

函数使用 isKey 判断路径类型,其判断逻辑主要包括:

javascript 复制代码
function isKey(value, object) {
  if (isArray(value)) {
    return false;
  }
  var type = typeof value;
  if (
    type == "number" ||
    type == "symbol" ||
    type == "boolean" ||
    value == null ||
    isSymbol(value)
  ) {
    return true;
  }
  return (
    reIsPlainProp.test(value) ||
    !reIsDeepProp.test(value) ||
    (object != null && value in Object(object))
  );
}
  • 数组形式的路径肯定是复杂路径
  • 数字、符号、布尔值、null 或 undefined 被视为简单键
  • 不包含特殊字符(如 .[)的字符串为简单键
  • 如果是对象的直接属性,也视为简单键

处理简单属性键

当路径是简单属性键时,使用 baseProperty 创建属性访问器:

javascript 复制代码
function baseProperty(key) {
  return function (object) {
    return object == null ? undefined : object[key];
  };
}

这个函数:

  • 返回一个接收对象的新函数
  • 检查对象是否为 null 或 undefined
  • 直接使用方括号语法 object[key] 访问属性
  • 返回对应的属性值或 undefined

处理复杂属性路径

当路径是复杂路径时,使用 basePropertyDeep 创建深层属性访问器:

javascript 复制代码
function basePropertyDeep(path) {
  return function (object) {
    return baseGet(object, path);
  };
}

basePropertyDeep 同样返回一个函数,但内部使用 baseGet 来处理嵌套属性访问:

javascript 复制代码
function baseGet(object, path) {
  path = castPath(path, object);

  var index = 0,
    length = path.length;

  while (object != null && index < length) {
    object = object[toKey(path[index++])];
  }
  return index && index == length ? object : undefined;
}

baseGet 函数:

  • 将路径标准化为数组
  • 循环遍历路径的每一段
  • 逐层访问对象的嵌套属性
  • 处理 null 和 undefined 值
  • 返回最终结果或 undefined

性能优化

property 函数的实现体现了性能优化:

  • 对于简单属性键,使用更直接高效的 baseProperty
  • 对于复杂路径,使用功能更完整的 basePropertyDeep
  • 避免在简单情况下进行不必要的路径解析和处理

总结

property 函数虽然实现简单,但它是 Lodash 中极其实用的工具函数,体现了几个重要的设计原则:

  1. 简洁接口:以单一参数创建强大的属性访问器
  2. 策略模式:根据路径类型智能选择最优实现
  3. 函数式设计:返回纯函数,支持函数组合,无副作用
  4. 性能优化:区分简单和复杂情况,提供专门优化
  5. 代码复用:利用基础函数构建更高级的抽象

这个函数展示了 Lodash 如何用简单的函数创建强大的工具,使开发者能够以更简洁、更声明式的方式处理数据。它是函数式编程在 JavaScript 中的绝佳实践案例,通过组合小型专用函数构建出灵活而强大的应用。

相关推荐
键指江湖23 分钟前
React 在组件间共享状态
前端·javascript·react.js
烛阴35 分钟前
零基础必看!Express 项目 .env 配置,开发、测试、生产环境轻松搞定!
javascript·后端·express
诸葛亮的芭蕉扇42 分钟前
D3路网图技术文档
前端·javascript·vue.js·microsoft
小离a_a44 分钟前
小程序css实现容器内 数据滚动 无缝衔接 点击暂停
前端·css·小程序
徐小夕1 小时前
花了2个月时间研究了市面上的4款开源表格组件,崩溃了,决定自己写一款
前端·javascript·react.js
by————组态2 小时前
低代码 Web 组态
前端·人工智能·物联网·低代码·数学建模·组态
拉不动的猪2 小时前
UniApp金融理财产品项目简单介绍
前端·javascript·面试
菜冬眠。2 小时前
uni-app/微信小程序接入腾讯位置服务地图选点插件
前端·微信小程序·uni-app
jayson.h2 小时前
pdf解密程序
java·前端·pdf
萌萌哒草头将军2 小时前
😡😡😡早知道有这两个 VueRouter 增强插件,我还加什么班!🚀🚀🚀
前端·vue.js·vue-router