)
es-toolkit 的 result 函数自动调用路径上函数的取值工具Lodash 兼容实现解析【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkitresult是 es-toolkit 的compatLodash 兼容模块提供的取值函数与get的最大区别在于它在解析对象路径时若遇到函数会以对象为this自动调用它并把最终值若仍是函数也执行后返回。本文围绕其 API 用法、参数语义、源码实现与边界行为展开帮助你在从 Lodash 迁移到 es-toolkit 时安全、高效地使用result并理解它与get、可选链?.的取舍。一、result 是什么一次会执行函数的路径取值result从对象路径中取值一旦解析路径的过程中遇到函数就立即调用它并用返回值继续往下解析最终值如果还是函数同样会被调用并返回其执行结果。const result result(obj, path, defaultValue);它的典型使用场景是数据结构中某些节点是惰性计算的 getter 或方法而你希望取值时自动触发这些计算无需手动判断类型再调用。在 src/compat/object/result.ts 中其 JSDoc 明确描述了这一行为If the resolved value is a function, it is invoked with the object as itsthiscontext. If the value isundefined, thedefaultValueis returned.二、官方警告优先使用 get 或可选链原文档开篇给出了明确的使用建议见 英文版文档由于复杂的路径处理与函数调用逻辑result函数运行较慢。请优先使用更快、更现代的get函数或可选链?.。这意味着result主要面向Lodash 兼容迁移场景当旧代码依赖 Lodash_.result的自动调用函数语义时可以用es-toolkit/compat的result无缝替换而在新代码中普通取值应优先使用 src/compat/object/get.ts 提供的get或直接使用原生可选链以获得更好的性能和更少的意外副作用。三、完整用法示例从es-toolkit/compat导入后result覆盖了从普通取值到深层函数调用的多种场景。import { result } from es-toolkit/compat; // 1. 基础用法普通值 const obj { a: { b: { c: 3 } } }; const value result(obj, a.b.c); // 结果: 3 // 2. 自动函数调用 const objWithFunc { compute: () ({ value: 42 }), getValue: function () { return this.compute().value; }, }; const computed result(objWithFunc, getValue); // 结果: 42getValue 函数被调用 // 3. 路径上的函数调用 const nested { data: () ({ user: { getName: () John } }), }; const name result(nested, data.user.getName); // 结果: Johndata() 和 getName() 都被调用 // 4. 使用默认值 const incomplete { a: { b: null } }; const withDefault result(incomplete, a.b.c, default value); // 结果: default value路径解析到 undefined返回默认值 // 5. 默认值为函数 const withFuncDefault result(incomplete, a.b.c, () computed default); // 结果: computed default默认值函数被调用 // 6. 数组路径 const arrayPath result(objWithFunc, [getValue]); // 结果: 42 // 7. 动态默认值惰性生成 const dynamic result(incomplete, missing.path, function () { return Generated at ${new Date().toISOString()}; }); // 结果: 包含当前时间的字符串注意第 4 个例子{ a: { b: null } }沿a.b.c取值时b为null继续向下访问属性会得到undefined因此命中默认值分支。而如果路径最终解析到的值本身是null则会原样返回null不会触发默认值这一点在测试 src/compat/object/result.spec.ts 的 should be able to returnnullvalues 用例中得到验证。四、this 上下文的保持result在调用路径上的函数时会将函数绑定到当前正在遍历的对象上调用因此方法内部访问this完全正常import { result } from es-toolkit/compat; const calculator { multiplier: 2, compute: function () { return 10 * this.multiplier; }, }; const calculatedValue result(calculator, compute); // 结果: 20this.multiplier 被正确引用这一点在源码中对应 src/compat/object/result.ts 的object typeof value function ? value.call(object) : value;——每次遇到函数都用value.call(object)以当前对象为this执行并将结果作为下一轮遍历的对象。测试用例 should invoke deep property methods with the correctthisbinding 也专门验证了深层路径上的方法能正确访问this。五、参数与返回值参数参数类型说明objectany要查询的对象。允许为null/undefined此时直接返回默认值或undefined见下节边界行为pathPropertyPath要获取的属性路径。可以是字符串如a.b.c、a[0].b、数组如[a, b, c]也可以是数字、Symbol 等属性键。类型定义见 src/compat/_internal/PropertyPath.tstype PropertyPath ManyPropertyKeydefaultValueR \| ((...args: any[]) R)可选当解析结果为undefined时返回的默认值。若传入的是函数则会调用它并返回其结果注意调用时同样以object为this见 src/compat/object/result.ts返回值类型为R返回最终解析出的值。路径上遇到的函数会被调用如果最终值也是函数同样调用后返回结果若任一步解析到undefined返回默认值或默认值函数的执行结果。六、源码实现核心循环与路径预处理result的实现非常精简核心逻辑位于 src/compat/object/result.tsexport function resultR(object: any, path: PropertyPath, defaultValue?: R | ((...args: any[]) R)): R { if (isKey(path, object)) { path [path]; } else if (!Array.isArray(path)) { path toPath(toString(path)); } const pathLength Math.max(path.length, 1); for (let index 0; index pathLength; index) { const value object null ? undefined : object[toKey(path[index])]; if (value undefined) { return typeof defaultValue function ? (defaultValue as any).call(object) : (defaultValue as R); } object typeof value function ? value.call(object) : value; } return object; }整个执行流程可以拆解为三个阶段路径归一化第 40–44 行先用 src/compat/_internal/isKey.ts 判断path是否只是单层属性名如a、数字、Symbol、布尔值、null或恰好是对象自有键是则包装成单元素数组否则若不是数组则通过 src/compat/util/toPath.ts 把字符串解析为路径段数组。isKey内部用regexIsPlainProp/^\w*$/与regexIsDeepProp匹配.或[...]下标区分纯属性名与深层路径。逐段遍历第 48–56 行pathLength Math.max(path.length, 1)保证空路径也能进入至少一轮循环空路径下首轮value为object[undefined]通常为undefined从而返回默认值测试 should return the default value whenpathis empty 验证了result({}, [], a) a。每一轮用 src/compat/_internal/toKey.ts 把段转换为字符串或 Symbol 键——toKey对-0特殊处理为字符串-0保持符号见测试 should preserve the sign of0。函数即调第 55 行typeof value function时以value.call(object)调用并把结果赋给object继续遍历否则直接作为下一轮的查询对象。七、路径解析细节toPath 的解析规则当传入字符串路径时src/compat/util/toPath.ts 承担了 Lodash 风格的路径解析它支持点号路径a.b.c→[a, b, c]括号下标a[b][c]→[a, b, c]引号包裹的键a[b.c].d→[a, b.c, d]引号内的点号不再作为分隔符前导点号.a.b.c→[, a, b, c]空路径→[]测试 should handle complex paths 进一步验证了a[-1.23][[\\b\\]].c[\[\\\d\\\]\][\ne\n][f].g这种包含转义引号、换行符、负小数下标的极端路径也能正确解析src/compat/object/result.spec.ts。此外从源码可以推断isKey对对象已拥有该属性名的情况也会直接当作单键处理Object.hasOwn(object, value)分支这意味着result({ a.b: 1, a: { b: 2 } }, a.b)会返回1而非2与测试 should get a key over a path 的预期一致。八、边界行为来自测试的完整证据src/compat/object/result.spec.ts 覆盖了大量边界场景整理如下场景行为测试用例object为null/undefined返回undefined无默认值时即使路径指向constructor等原型链属性也不会报错should returnundefinedwhenobjectis nullish路径中途缺失返回undefined或默认值如a[1].b.cshould returnundefinedif parts ofpathare missing最终值为null原样返回null不触发默认值should be able to returnnullvalues数组路径不会把数组强转成字符串[a, b, c]与a.b.c行为一致除非对象真有a,b,c键should not coerce array paths to strings空括号a[]可解析到{ a: { : 1 } }中的空字符串键should not ignore empty bracketsSymbol 键支持 Symbol 作为路径段should get symbol keyed property values非普通对象沿原型链解析测试通过Number.prototype注入属性验证should followpathover non-plain objects默认值为任意 falsy 值emptiesfalse、、0等都能作为默认值正确返回should return the default value forundefinedvalues这些用例与 Lodash 的_.result语义保持了一致是compat模块可直接替换承诺的保障。result已通过 src/compat/compat.ts 的export { result } from ./object/result.ts对外暴露。九、与 get 的对比何时用哪个result与get的核心差异在于是否执行函数get只做取值遇到函数原样返回函数引用不调用遇到undefined返回默认值。适合绝大多数普通数据访问且在null对象上直接返回默认值而不抛错。result沿路径自动执行所有遇到的函数最终值若为函数也执行。适合兼容 Lodash 旧代码、或数据结构中嵌入了惰性 getter 的迁移场景。原生?.现代写法性能最好但不会调用函数、也不支持字符串路径的解析需配合a?.b?.c逐层书写。从源码实现看result的循环里每次都要做typeof value function判断与value.call(object)绑定加上isKey/toPath的路径预处理开销这就是官方警告其较慢的原因所在。因此建议新代码优先get或?.仅在需要 Lodash 兼容时使用result。十、小结result(obj, path, defaultValue)沿路径取值路径上的函数以当前对象为this自动调用最终值为函数时同样执行。默认值既可以是普通值也可以是函数函数会被调用并返回结果。路径支持字符串含点号、括号下标、引号转义、数组、数字、Symbol 等多种形式解析规则与 Lodash 保持一致。完整边界行为null/undefined对象、null值返回、空路径、原型链解析等均有测试用例保障可在 src/compat/object/result.spec.ts 中逐一查阅。性能敏感场景请遵循官方建议改用 get 或可选链。如需查看函数完整类型签名与 JSDoc 示例可阅读 src/compat/object/result.tsLodash 兼容模块的完整导出清单见 src/compat/compat.ts。【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考