
es-toolkit set 深度指南3 种路径语法写入嵌套对象动态 key 一步到位【免费下载链接】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数据 key 从后端配置拼出来时往user.address.city写个值这种需求用obj?.a?.b v一行都写不出——层数在编译期根本定不了。es-toolkit 兼容层的set就是为这类场景准备的接收一个动态路径字符串在任意深度写入值缺什么节点就自动补什么节点。快速上手8 行代码跑通最小用例import { set } from es-toolkit/compat; const config {}; set(config, user.profile.city, 上海); console.log(config); // { user: { profile: { city: 上海 } } }config原本只是个空对象set沿着user.profile.city逐层建好容器把值写进最深处。实现上它只是 src/compat/object/set.ts 里 5 行的薄壳真正的活都交给了updateWithexport function set(obj, path, value) { return updateWith(obj, path, () value, () undefined); }高频场景场景 1路径来自运行期写死赋值不现实表单字段映射、远端下发的配置项路径只能运行期才知道const field request.body.target; // 例如 theme.mode set(state, field, dark);原理一句话字符串路径先被toPath拆成段数组点号、括号都是分隔符再逐段走树。场景 2从零开始建结构连下标跳跃都帮你兜住const doc {}; set(doc, items[1].price, 42); // { items: [undefined, { price: 42 }] }中间节点不存在时set会看下一段是不是下标是就建数组[]否则建对象{}判断逻辑在 src/compat/_internal/isIndex.ts。注意这里跳过下标 0items[0]是空洞——这是稀疏数组for...of遍历时会被跳过别意外。场景 3键名本身带点号用括号或数组路径绕过set(obj, a[b.c].d, 1); // 引号里的点不拆分 → obj.a[b.c].d set(obj, [a.b], 2); // 数组元素按字面键 → obj[a.b]两条规则都指向同一个结论字符串路径里带引号或带括号的段和数组形式的单个元素都当作字面键名不做二次拆分。这在键名来自外部输入、无法预测时能救命。场景 4往数组里按位置改值const arr [1, 2, 3]; set(arr, 1, 4); console.log(arr); // [1, 4, 3]数字直接当下标用不需要字符串包装对象套数组、数组套对象这种混合嵌套同样支持比如set({}, users[0].name, a)会得到{ users: [{ name: a }] }。⚠️ 容易踩坑的隐性规则以下行为都有测试用例背书见 src/compat/object/set.spec.ts迁移 lodash 代码时建议逐条过一遍隐性规则输入 → 输出为什么原地修改返回同一个引用const r set(o, y, 2)后r o为trueupdateWith全程在改原对象最后原样返回不做拷贝数字下标建数组其余建对象set({}, a[1].b, 1)→{ a: [undefined, { b: 1 }] }下一段通过isIndex判定非负整数或/^(?:0\|[1-9]\d*)$/字符串才建[]nullish 输入静默返回set(null, a.b, 1)返回null不抛错函数入口先判空直接 return危险键名静默中止set({}, a.__proto__.x, 1)不写任何东西每段键名都过isUnsafeToWriteProperty命中__proto__/constructor/prototype立即中止见 src/_internal/isUnsafeToWriteProperty.ts中间是基本类型会被整个覆盖set({ a: }, a.b, 2)→{ a: { b: 2 } }中间节点不是对象就无条件重建容器原值直接丢弃额外一个细节写入前会用eq比较目标位置的值相同就跳过赋值不会触发多余的 setter测试里专门给带 setter 的属性做了断言。性能与替代方案官方文档在 docs/compat/reference/object/set.md 开头就给了警告set走完整路径解析 get读旧值 逐段建容器 逐段赋值的流水线速度较慢优先用直接赋值或解构赋值。需求现代语法set路径编译期已知obj.a.b.c 1直接赋值最快能做但纯属杀鸡用牛刀不可变更新{ ...obj, a: { ...obj.a, b: 1 } }做不到它本来就改原对象路径运行期才知道得手写递归写入✅ 核心用途中间节点缺失需自动创建手写reduce或Object.assign链✅ 内置lodash_.set存量代码迁移需重写✅ 行为对齐结论很直白只要路径在编译期能写死就该放弃set。它的价值全部押在路径是动态的这一条上为此付出的代价是每次调用都多一整套解析和判空逻辑。️ 进阶延伸默认下标→数组、其余→对象的建容器策略不够用时换setWith——它多收一个 customizer 回调返回undefined时回落到默认策略import { setWith } from es-toolkit/compat; const obj {}; setWith(obj, [0][1], v, () []); // { 0: [undefined, v] }反过来set就是customizer 恒返回undefined的setWith特例见 src/compat/object/setWith.ts。读取侧配套的是get(obj, a.b.c, default)同样支持路径语法且 null 安全。决策清单✅该用路径是动态字符串用户输入 / 配置下发 / lodash 迁移✅该用需要缺失节点自动创建且不想手写递归❌不该用路径编译期已知直接obj.a.b 1更快更省❌不该用需要不可变语义——set永远原地修改并返回原引用❌不该用对null/undefined期望有副作用——它静默返回原值错误会被吞掉一句话总结set是动态路径写入的瑞士军刀不是性能工具。【免费下载链接】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),仅供参考