es-toolkit 兼容层 updateWith 详解:用 customizer 精确控制嵌套对象路径的创建
es-toolkit 兼容层 updateWith 详解用 customizer 精确控制嵌套对象路径的创建【免费下载链接】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导读本文以 es-toolkit 兼容层compat中面向 lodash 兼容的updateWith函数为核心讲解如何在一个深层嵌套对象中通过 updater 函数更新指定路径的值并利用 customizer 回调控制路径缺失时中间对象数组或普通对象的创建形态。读完本文你将掌握updateWith的完整签名、字符串/数组两种路径写法、customizer 的三个入参与返回约定以及其底层实现如何协同get、toPath、assignValue、isIndex等内部模块完成路径解析与安全写入。函数概览updateWith是 es-toolkit 兼容层中update的增强版本官方参考文档。它与update的唯一区别在于当路径中的某一段不存在时update总是按「数字下标创建数组、其余创建普通对象」的默认规则补齐结构而updateWith允许你通过 customizer 自定义这一段中间容器究竟应该是什么。const updated updateWith(obj, path, updater, customizer);与 update / setWith 的关系在 src/compat/object/update.ts 中可以看到update实际上是updateWith的特例export function update(obj: object, path: PropertyPath, updater: (value: any) any): any { return updateWith(obj, path, updater, () undefined); }也就是说update等价于「customizer 恒返回undefined」的updateWith此时完全走默认的中间对象创建逻辑。而setWith则是用固定值替换 updater 的同类函数见 setWith 文档内部同样基于updateWith的路径遍历机制实现。基本用法更新已存在路径上的值当路径已存在时updateWith的行为与update完全一致取出旧值传给 updater用返回值替换旧值。import { updateWith } from es-toolkit/compat; // 基本行为与 update 相同 const object { a: [{ b: { c: 3 } }] }; updateWith(object, a[0].b.c, n n * n); // { a: [{ b: { c: 9 } }] } // 使用数组形式的路径 updateWith(object, [a, 0, b, c], n n 10); // { a: [{ b: { c: 13 } }] }路径的两种写法字符串路径如a[0].b.c支持点号与括号下标混合语法空括号a[]会被解析为字面键测试 updateWith.spec.ts 验证了这一点转义写法如a[-1.23][[\b\]].c也能正确解析。数组路径如[a, 0, b, c]元素可以是字符串、数字或 symbol。数组路径不会被强制转成字符串[a, b, c]不会匹配a,b,c键同时也不会忽略其中包含点号或空字符串的段见 src/compat/object/updateWith.spec.ts 中「not coerce array paths to strings」「handle empty paths」两组用例。核心能力用 customizer 控制中间对象的创建当路径不存在时updateWith需要沿途创建中间容器。默认规则是若下一段路径是数组下标则创建数组否则创建普通对象。而 customizer 可以改写这一规则import { updateWith } from es-toolkit/compat; const object {}; // 使用 Object 构造函数作为 customizer强制创建普通对象而非数组 updateWith(object, [0][1], () a, Object); // { 0: { 1: a } } // 默认行为会是 { 0: [a] }customizer 接收(value, key, object)三个参数其中value是当前路径段的旧值通常为undefinedkey是要创建的键object是当前所在的父对象。它返回undefined时回退到默认行为返回其他任意值则作为新建的中间容器import { updateWith } from es-toolkit/compat; const customizer (value: any, key: string, object: any) { // 对数字键创建普通对象而不是数组 if (!isNaN(Number(key))) { return {}; } }; const result {}; updateWith(result, [0][1], () value, customizer); // { 0: { 1: value } }路径已存在时 customizer 不会被调用customizer 只负责「创建缺失的中间对象」因此当整条路径都已经存在时它不会被触发import { updateWith } from es-toolkit/compat; const object { a: { b: 1 } }; updateWith( object, a.b, n n * 2, () { console.log(Not called); // 不会被调用 return {}; } ); // { a: { b: 2 } }测试 src/compat/object/updateWith.spec.ts 也专门验证了「customizer 修改原对象时最后一级仍应被正确更新」这一边界行为。源码级原理updateWith 的执行链路updateWith的实现位于 src/compat/object/updateWith.ts核心流程分为四步1. 空值保护if (obj null !isObject(obj)) { return obj; }当传入null或undefined时直接原样返回不会抛错对应测试 updateWith.spec.ts 中的 nullish 用例。2. 路径解析let resolvedPath: PropertyKey[]; if (isKey(path, obj)) { resolvedPath [path]; } else if (Array.isArray(path)) { resolvedPath path; } else { resolvedPath toPath(path); }若路径本身是对象的已有键isKey判定直接作为单段路径数组路径原样保留逐段使用字符串路径交给toPathsrc/compat/util/toPath.ts解析成段数组支持点号与括号语法。3. 计算新值const updateValue updater(get(obj, resolvedPath));先通过get读取路径当前的旧值交给 updater 计算出新值再开始逐段写入。4. 逐段写入与中间对象决策for (let i 0; i resolvedPath.length current ! null; i) { const key toKey(resolvedPath[i]); if (isUnsafeToWriteProperty(key)) { return obj; } let newValue: unknown; if (i resolvedPath.length - 1) { newValue updateValue; } else { const objValue current[key]; const customizerResult customizer?.(objValue, key as string, obj); newValue customizerResult ! undefined ? customizerResult : isObject(objValue) ? objValue : isIndex(resolvedPath[i 1]) ? [] : {}; } assignValue(current, key, newValue); current current[key]; }这段循环揭示了三个关键设计中间对象的决策优先级customizer 返回值 已存在的对象保留原引用 下一段是数组下标则建数组 否则建普通对象。其中「下一段是否为数组下标」由 src/compat/_internal/isIndex.ts 判定——它只把无符号十进制整数0或[1-9]\d*视为下标因此1a这类以数字开头但非下标的键仍会创建普通对象测试 updateWith.spec.ts 专门覆盖了这一点。原型链污染防护每段写入前都会调用isUnsafeToWritePropertysrc/_internal/isUnsafeToWriteProperty.ts检查__proto__、constructor、prototype等危险键一旦命中立即中止整个更新并返回原对象。测试 updateWith.spec.ts 验证了a[0][__proto__].b、constructor.prototype.polluted等路径都不会污染全局Object.prototype。惰性写入最终赋值通过 src/compat/_internal/assignValue.ts 完成它会在新旧值相同时跳过赋值避免触发不必要的 setter这对NaN、对象引用等场景同样适用测试 updateWith.spec.ts。参数与返回值参数类型说明objTobject要修改的目标对象。传入null/undefined时原样返回不抛错pathPropertyKey \| readonly PropertyKey[]要更新的属性路径可用字符串点号/括号语法或数组表示updater(oldValue: any) any接收旧值、返回新值的函数customizer(value: any, key: string, object: T) any可选决定缺失路径段要创建什么中间容器返回undefined时走默认逻辑下标建数组、其余建对象返回值T——修改后的原对象原地修改与update一致测试中断言actual与object是同一引用。实践建议与注意事项官方文档在页面开头明确提示updateWith因复杂的路径解析与 customizer 处理而运行较慢在性能敏感的代码中应优先使用现代的直接属性赋值或可选链optional chaining写法updateWith更适合需要动态路径、且必须控制中间容器形态的 lodash 迁移场景。使用时的几个要点路径尽量用数组形式可避免字符串解析的歧义也能正确处理包含点号、空串的键customizer 记得在不需要定制时返回undefined返回其他值会强制替换已存在的对象可能破坏原有引用结构切勿传入__proto__/constructor/prototype相关路径虽然实现内部会拦截并中止但这类写法本身就是反模式updateWith会原地修改对象若不想改动原对象请先自行浅拷贝/深拷贝。相关函数与延伸阅读update 参考文档update是updateWith的特例customizer 恒为undefinedsetWith 参考文档以固定值代替 updater同样支持 customizer 控制中间对象形态updateWith 实现源码核心遍历与写入逻辑updateWith 测试用例覆盖路径解析、原型链污染防护、符号键、边界路径等 19 组场景set 相关实现 与 get 实现updateWith读取旧值依赖get写入依赖assignValue三者共享同一套路径模型。【免费下载链接】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),仅供参考

相关新闻

用固有噪声训练聚类模型,实现光纤水声信号识别

用固有噪声训练聚类模型,实现光纤水声信号识别

简介:基于Python深度学习的光纤传感水声信号识别方法配套资源包,以系统自身固有噪声信号的分解分量作为训练数据,聚焦最优聚类模型,面向毕业设计、信号处理与人工智能应用开发人群。方法借助深度学习自动提取特征,可对…

2026/10/24 0:32:56 阅读更多 →
VRPSPDTW建模与求解:同步取送货+时间窗的整数规划实战

VRPSPDTW建模与求解:同步取送货+时间窗的整数规划实战

简介:本资源面向运筹优化、物流工程及智能算法方向的高校师生与科研人员,聚焦带时间窗与同时取送货约束的车辆路径问题(VRPSPDTW),提供一套完整可运行的MATLAB求解方案。资源包含10个文件:5个核心M文件&…

2026/10/24 3:55:53 阅读更多 →
K-means实战:电商用户分层从原理到sklearn实现与运营落地

K-means实战:电商用户分层从原理到sklearn实现与运营落地

K-means这个算法,说实话很神奇。你说它简单吧,面试必考、数据分析必用、用户分层必提,几乎是机器学习入门绕不开的第一个模型;你说它复杂吧,真正做业务的人天天用它做人群划分、商品聚类、异常检测,用了好几…

2026/10/25 16:21:54 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/26 12:00:21 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/27 4:06:49 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/27 7:21:53 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/26 12:00:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/27 6:20:47 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/27 4:06:50 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 13:55:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 7:21:50 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 8:34:37 阅读更多 →