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/9/22 4:41:30 阅读更多 →
VRPSPDTW建模与求解:同步取送货+时间窗的整数规划实战

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

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

2026/9/21 15:39:10 阅读更多 →
K-means实战:电商用户分层从原理到sklearn实现与运营落地

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

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

2026/9/21 15:39:17 阅读更多 →

最新新闻

下箭头怎么打:从键盘到源码的避坑指南

下箭头怎么打:从键盘到源码的避坑指南

下箭头怎么打:从键盘到源码的避坑指南 学会语法却不知怎么搭项目?别急,这不仅是语法问题,更是工具链配置的深坑。很多开发者在代码里敲了半天 ↓ 或者 Unicode…

2026/9/22 4:41:03 阅读更多 →
w7系统之家实战:3个细节搞定源码解析,拒绝跑不通

w7系统之家实战:3个细节搞定源码解析,拒绝跑不通

w7系统之家实战:3个细节搞定源码解析,拒绝跑不通 复制来的代码跑不通,报错信息满屏飞,新手第一反应往往是“是不是我电脑配置不行?”或者“这段代码是不是有Bug?”。别急,这通常不是代码的问题,而是你对底层逻辑的理解存在断层。在…

2026/9/22 4:41:03 阅读更多 →
3步搞定vn出装:保姆级教程带你从零到跑通

3步搞定vn出装:保姆级教程带你从零到跑通

3步搞定vn出装:保姆级教程带你从零到跑通 复制来的代码跑不通,报错信息看得人脑壳疼?别慌,这不是你代码写得烂,是环境没配对。很多后端老哥接手新项目时,总被那些看似简单的配置卡住,其实只要理清脉络,半小时就能搞定。这篇保姆级教程,专门拆解【…

2026/9/22 4:41:03 阅读更多 →
苹果手机已停用怎么办?3步找回数据的保姆级教程

苹果手机已停用怎么办?3步找回数据的保姆级教程

苹果手机已停用怎么办?3步找回数据的保姆级教程 刚拿到一台旧 iPhone,或者不小心输错密码导致屏幕变黑,提示“iPhone…

2026/9/22 4:40:03 阅读更多 →
仙剑奇侠传3硬盘版性能优化实战3个关键步骤

仙剑奇侠传3硬盘版性能优化实战3个关键步骤

仙剑奇侠传3硬盘版性能优化实战3个关键步骤 别再去啃那几百页的官方技术文档了,全是废话,抓不住重点。我踩了无数坑,发现 性能优化 的真谛就在代码细节里。今天直接上硬菜,不讲虚的。 性能瓶颈定位…

2026/9/22 4:40:03 阅读更多 →
量比选股公式速查手册:面试突击避坑指南

量比选股公式速查手册:面试突击避坑指南

量比选股公式速查手册:面试突击避坑指南 配置环境就卡半天,代码跑不通,面试官问起“量比”你又支支吾吾?这种痛苦我太懂了。别慌,今天这篇【量比选股公式】速查手册,就是为你准备的救命稻草。咱们不整虚的,直接上干货,把那些让你头秃的面试考点拆碎了…

2026/9/22 4:40:03 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →