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
函数的实现非常简洁明了:
- 接收一个路径参数
path
,可以是字符串、数组或符号 - 判断路径是否为简单属性键(使用
isKey
函数) - 如果是简单属性键(如
'name'
),使用baseProperty
创建简单访问器 - 如果是复杂路径(如
'user.profile.name'
或数组),使用basePropertyDeep
创建深层访问器 - 返回创建的访问器函数,该函数可以传入对象来获取属性值
这种分治策略根据路径的复杂度选择最优的实现方式,既保证了功能完整性,又考虑了性能优化。
源码解析
路径类型判断
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 中极其实用的工具函数,体现了几个重要的设计原则:
- 简洁接口:以单一参数创建强大的属性访问器
- 策略模式:根据路径类型智能选择最优实现
- 函数式设计:返回纯函数,支持函数组合,无副作用
- 性能优化:区分简单和复杂情况,提供专门优化
- 代码复用:利用基础函数构建更高级的抽象
这个函数展示了 Lodash 如何用简单的函数创建强大的工具,使开发者能够以更简洁、更声明式的方式处理数据。它是函数式编程在 JavaScript 中的绝佳实践案例,通过组合小型专用函数构建出灵活而强大的应用。