尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

es-toolkit mapKeys 完全指南:用函数转换对象键并保持值不变的现代实现

es-toolkit mapKeys 完全指南:用函数转换对象键并保持值不变的现代实现 es-toolkit mapKeys 完全指南用函数转换对象键并保持值不变的现代实现【免费下载链接】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-toolkitmapKeys是 es-toolkit 对象Object模块中用于批量转换对象键的工具函数它接受一个对象和一个生成新键的回调函数返回一个值保持不变、键被替换的全新对象。本指南以 docs/ja/reference/object/mapKeys.md 为核心结合 源码实现 与 单元测试 深入讲解其用法、类型签名、底层原理与边界行为读完你将掌握键重命名、键规范化、键与值组合等常见数据转换场景的落地写法并能理解它与mapValues、mapKeysAsync的分工。一、函数概览一次调用完成全量键转换mapKeys的核心语义可以用一句话概括遍历对象的每个自有可枚举属性把属性名交给getNewKey函数计算出一个新键并用新键与原值组成新对象返回。const newObj mapKeys(object, getNewKey);它特别适合以下场景给一批键统一添加前缀或后缀如接口字段加prefix_键大小写规范化如转大写、转小写、转 camelCase利用键与值的组合生成业务语义更强的新键如${key}_${value}把数字键或特殊字符键改写成更安全、更可读的键。值得注意的是mapKeys不会修改原对象而是返回一个新对象且它只转换键值原样保留。这与只转换值的 mapValues 恰好互补。二、使用方式与代码示例按官方文档的用法mapKeys通过es-toolkit/object子路径导入import { mapKeys } from es-toolkit/object;2.1 给键添加前缀const obj { a: 1, b: 2 }; const prefixed mapKeys(obj, (value, key) prefix_${key}); // prefixed 是 { prefix_a: 1, prefix_b: 2 }2.2 组合键和值生成新键const combined mapKeys(obj, (value, key) ${key}${value}); // combined 是 { a1: 1, b2: 2 }2.3 将键转换为大写const uppercased mapKeys(obj, (value, key) key.toString().toUpperCase()); // uppercased 是 { A: 1, B: 2 }三个示例展示了回调的三个核心用法只依赖key、同时依赖key与value、以及先对key做类型/格式转换后再返回。回调的完整签名见下节。三、参数与返回值详解参数objectT extends RecordPropertyKey, any需要转换键的对象。泛型约束要求它满足RecordPropertyKey, any即键类型属于PropertyKeystring | number | symbol的普通对象。getNewKey(value: T[keyof T], key: ObjectKeysT, object: T) K生成新键的函数。它按序遍历对象的每个自有可枚举属性依次接收三个参数value当前属性的值类型为T[keyof T]key当前属性的键类型为ObjectKeysT见下文第四节object整个原对象类型为T可用于基于全局状态生成键。关于ObjectKeysT的类型细节参见 src/types/ObjectKeys.ts 及 类型文档。返回值RecordK, T[keyof T]返回键已转换、值保持不变的新对象。新键类型K由getNewKey的返回值推断因此 TypeScript 能精确推导出结果对象的键集合与值类型。四、源码级实现原理mapKeys的实现非常精简完整代码位于 src/object/mapKeys.tsexport function mapKeysT extends RecordPropertyKey, any, K extends PropertyKey( object: T, getNewKey: (value: T[keyof T], key: ObjectKeysT, object: T) K ): RecordK, T[keyof T] { const result {} as RecordK, T[keyof T]; const keys Object.keys(object) as ArrayObjectKeysT; for (let i 0; i keys.length; i) { const key keys[i]; const value object[key]; result[getNewKey(value, key, object)] value; } return result; }从实现中可以看出几个关键设计遍历入口是Object.keys而非for...in这意味着只有对象的自有可枚举属性会被转换原型链上的属性不会进入结果也天然排除了 Symbol 键Object.keys的运行时行为。这一点与ObjectKeysT类型的设计完全对应。每次迭代都对object[key]做一次属性读取再调用getNewKey(value, key, object)最后执行result[新键] 原值——顺序清晰无副作用依赖。不修改原对象函数内部只新建result对象并向其写入因此调用后原对象保持不变符合函数式工具的一贯风格。普通for循环而非forEach/reduce与 es-toolkit 追求性能的一贯风格一致避免多余的回调闭包开销。键冲突时的行为可从实现推断由于实现是“后写覆盖”当getNewKey对多个不同原键返回相同的新键时后遍历到的属性会覆盖先遍历到的属性最终保留的是Object.keys顺序中靠后的那个值。例如mapKeys({ a: 1, b: 2 }, () same); // 结果是 { same: 2 }因此在使用mapKeys前应确认回调生成的新键不会发生冲突否则结果会丢失部分值。数字键的字符串化Object.keys会把数字键统一转为字符串因此mapKeys处理数字键时回调收到的key是字符串。测试用例 src/object/mapKeys.spec.ts 中有对应的验证it(should iterate over and map the object using its own number keys, () { expect(mapKeys({ 1: a, 2: b, 3: c }, (_, key) Number(key) * 2)).toEqual({ 2: a, 4: b, 6: c }); });可见在回调中手动Number(key)把字符串键转回数字即可实现基于数值的新键计算。五、ObjectKeysT类型让键类型贴合运行时回调第二参数的类型是ObjectKeysT而非keyof T这是本函数在类型设计上最有讲究的地方。src/types/ObjectKeys.ts 中的定义如下export type ObjectKeysT ${Excludekeyof T, symbol};其效果详见 ObjectKeys 类型文档数字键被模板字符串类型转为字符串形式ObjectKeys{ a: number; 1: string }得到a | 1而keyof会得到a | 1Symbol 键被排除ObjectKeys{ a: number; [sym]: string }得到a索引签名收敛为字符串形式ObjectKeysRecordstring, number是stringObjectKeysRecordnumber, string是${number}。这与Object.keys的运行时行为键永远是字符串、不含 Symbol保持一致能避免“类型说是数字键、运行时却是字符串键”的错位是给Object.keys结果做类型标注时的推荐工具。六、与相邻工具的分工mapValues与mapKeysAsync在 es-toolkit 的 object 模块入口 中mapKeys与一组键/值转换工具并列导出理解它们的差异有助于选对工具函数转换对象保留对象同步/异步mapKeys键值同步mapValues值键同步mapKeysAsync键值异步支持并发度控制mapValues(object, getNewValue)与mapKeys镜像对称——键原样保留值由回调重新计算如mapValues({ a: 1, b: 2 }, (value) value * 2)得到{ a: 2, b: 4 }。两者配合使用即可分别完成键与值的独立改造。mapKeysAsync当回调需要执行异步操作如基于远程数据生成键时使用其实现位于 src/object/mapKeysAsync.ts。它通过Promise.all并行处理所有键并支持传入{ concurrency }选项限制并发数内部借助limitAsync实现适合大批量异步键转换场景const result await mapKeysAsync(obj, async (value, key) key value, { concurrency: 3 });七、实战建议与注意事项保持幂等与确定性getNewKey应当是一个纯函数——对相同的(value, key, object)永远返回相同的新键否则结果不可预测。防止键冲突如果新键可能重复需自行评估“后写覆盖”的语义是否符合预期见第四节。只处理自有可枚举属性需要包含继承属性时mapKeys并不适用需要自行实现基于for...in的版本。优先使用精确类型回调第二参数使用ObjectKeysT在需要把键转回数字、或与Object.keys的结果互操作时类型更贴近运行时能减少不必要的类型断言。导入路径按需从es-toolkit/object导入配合 es-toolkit 的 tree-shaking 能力可避免引入整个库减小打包体积。八、相关资源本文档源文件docs/ja/reference/object/mapKeys.md源码实现src/object/mapKeys.ts单元测试src/object/mapKeys.spec.ts底层类型src/types/ObjectKeys.ts对比实现src/object/mapValues.ts、src/object/mapKeysAsync.ts模块导出src/object/index.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),仅供参考
返回列表