十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

es-toolkit set 函数一篇讲透:路径写入、自动建嵌套、源码级避坑指南

es-toolkit set 函数一篇讲透:路径写入、自动建嵌套、源码级避坑指南 es-toolkit 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把老项目从 lodash 迁到 es-toolkit 时很多人会卡在这种地方大部分函数换个 import 就完事唯独_.set让人犹豫——路径往往是运行时拼出来的比如_.set(obj, field .value, v)没法直接赋值。好消息是es-toolkit set 函数来自 compat 兼容层就是 lodash set 替代的现成答案行为与_.set几乎逐行对齐可以整段照搬import { set } from es-toolkit/compat; const config {}; set(config, server.port, 8080); set(config, [cache, ttl], 3600);但在你开始全局替换之前先花三分钟搞清楚它到底怎么工作、坑藏在哪。es-toolkit compat set 快速上手三种路径写法签名一行说清set(object, path, value)—— 往object的path位置写value返回修改后的原对象本身。path的类型是PropertyPath定义在 src/compat/_internal/PropertyPath.ts白话解释可以是单个键字符串/数字/symbol也可以是键的数组三种写法都能用// 点号写法 set(obj, a.b.c, 4); // 括号写法 set(obj, users[0].name, John); // 数组写法 set(obj, [nested, array, 0], first);它的核心能力是按路径写入对象时自动创建嵌套结构路径中间哪一段不存在就自动补哪一段而且补出来的容器类型是智能的——下一段是数组下标就建数组否则建普通对象。const empty {}; set(empty, user.profile.name, John); console.log(empty); // { user: { profile: { name: John } } }这正是它和obj.a.b v拉开差距的地方直接赋值在这里会直接抛Cannot set properties of undefined。set 的路径到底怎么拆toPath 解析规则表所有字符串路径都会过一遍 src/compat/util/toPath.ts 的解析器。先给结论点号拆、括号拆、引号里的不拆、数字原样保留。路径写法解析结果规则a.b.c[a, b, c]点号拆分a[b][c][a, b, c]括号等价于点号a[b.c].d[a, b.c, d]引号内容不拆a..b[a, , b]连续点号产生空段.a.b[, a, b]前导点号是空键items[0][items, 0]下标以字符串保留有两个反直觉的点es-toolkit 路径解析里最容易理解错含点号的字符串不一定被拆。isKey判定它是普通键时比如把a.b当单个键名就不会拆。所以set(obj, a.b)和set(obj, [a.b])效果相同——都是写一个字面键名为a.b的属性。数组路径不走字符串解析原样使用。当键本身带点号、空格等特殊字符时数组写法是最稳的选择。set 行为避坑清单原地修改、稀疏数组与 null 安全这部分是线上最容易出问题的地方。⚠️原地修改不是不可变更新。const original { x: 1 }; const result set(original, y, 2); original result; // true同一个引用set直接改你传进去的对象。如果你的状态管理Redux、Zustand 之类靠引用变化触发更新一次set会让 UI 完全无感。需要不可变语义时用解构赋值或者先克隆再写。跳号下标会造出稀疏数组。const list {}; set(list, items[0], first); set(list, items[2], third); console.log(list.items); // [first, 空位, third]中间下标不会被填undefined而是留空洞JSON.stringify会输出null。下游代码若假定密集数组遍历和索引都会对不上。中间节点是基本类型时直接覆盖。比如set({ a: }, a.b, 2)会得到{ a: { b: 2 } }——原值被容器对象顶掉不报错也不提醒。null 安全。对象参数传null/undefined时不抛错原样返回。防御性写法很友好但要注意写入其实什么都没发生。原型污染防线。路径里出现__proto__这类危险键时函数直接中止并返回原对象污染不了原型链。这是它比手写obj[key] value循环多出来的一道安全保险。updateWith 流水线到底在干什么set 为什么慢源码视角看src/compat/object/set.ts 的全部实现就是 4 行委托export function setT extends object(obj: T, path: PropertyPath, value: any): T { return updateWith(obj, path, () value, () undefined); }也就是说每次调用的开销全在 src/compat/object/updateWith.ts 的流水线上路径归一化先试isKey判定再试数组最后才走toPath字符串解析先用get读当前值、再跑 updater 算新值——而set传的 updater 是恒返回目标值的箭头函数这一步纯属陪跑逐段遍历每段过一遍toKey归一化和isUnsafeToWriteProperty安全检查非末段还要看下一段是不是下标src/compat/_internal/isIndex.ts非负整数或匹配^(?:0|[1-9]\d*)$的字符串来决定建[]还是{}每段写入都走assignValue里面还有值相同就跳过赋值的优化避免触发多余的 setter。上图是 es-toolkit 与 lodash 在其他函数上的性能对比——库的核心卖点是快。但set住在兼容层里为了和 lodash 行为 100% 对齐上面这套兼容工序一段都不能省。所以官方文档开头就挂了警告路径在编译期已知时直接用直接赋值或解构赋值比 set 更快。set 和直接赋值怎么选场景对照表最后给一张决策表。判断逻辑一句话路径定死就别用 set路径动态且要自动建结构set 才是正解。场景推荐方案理由路径编译期固定obj.a.b.c value零开销可读性最好需要不可变更新{ ...obj, a: { ...obj.a, b: value } }触发引用变化状态管理友好只读不写obj?.a?.b?.c或get可选链是原生方案路径动态配置/用户输入/运行时拼接es-toolkit/compat的set直接赋值做不到且需自动建结构lodash 存量代码迁移期set/setWith与_.set/_.setWith行为逐行对齐要自定义中间容器Map、类实例等setWith customizer默认的下标建数组、其余建对象不够用时✅ es-toolkit compat set 的定位一句话它解决的是兼容性与动态路径问题不是性能问题。迁移存量代码用它替换_.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),仅供参考
返回列表