news 2026/9/16 14:57:14

es-toolkit/compat 的 mapKeys 完全指南:Lodash 兼容的对象键映射转换

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
es-toolkit/compat 的 mapKeys 完全指南:Lodash 兼容的对象键映射转换

es-toolkit/compat 的 mapKeys 完全指南:Lodash 兼容的对象键映射转换

【免费下载链接】es-toolkitA modern JavaScript utility library that's 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit

mapKeys是 es-toolkit 的 Lodash 兼容层(es-toolkit/compat)中用于"只改键、不改值"地重建对象的工具函数。本文基于 docs/ja/compat/reference/object/mapKeys.md 展开,结合 compat 实现 与 现代版实现 的源码细节,讲解其完整用法、参数约定、iteratee 简写机制与底层原理,帮助你安全地从 lodash 迁移并理解兼容层与原生实现之间的差异。

mapKeys 是什么

mapKeys会遍历对象的每一个自有可枚举字符串键属性,将每个键交给iteratee函数生成新键,并原样保留对应的值,最终返回一个全新的对象。它不会修改传入的原始对象,适合用于键名归一化(如统一为小写、加前缀、加命名空间)或根据值与键的组合生成更语义化的键名。

es-toolkit/compat中,它的行为与 lodash 的mapKeys保持一致,作为 drop-in replacement 使用:

const result = mapKeys(obj, iteratee);

基本用法与典型场景

mapKeys的签名与 lodash 一致:第一个参数是要转换键的对象(或类数组),第二个参数是键转换函数iteratee

import { mapKeys } from 'es-toolkit/compat';

给键添加前缀

const obj = { a: 1, b: 2, c: 3 }; const result = mapKeys(obj, (value, key) => 'prefix_' + key); // 结果: { prefix_a: 1, prefix_b: 2, prefix_c: 3 }

将键转换为大写

const data = { name: 'John', age: 30 }; const uppercased = mapKeys(data, (value, key) => key.toUpperCase()); // 结果: { NAME: 'John', AGE: 30 }

将数组索引转换为键

object参数接受ArrayLike<T>,因此数组也可以直接传入,iteratee的第二个参数此时为索引:

const arr = ['apple', 'banana', 'orange']; const indexed = mapKeys(arr, (value, index) => `item_${index}`); // 结果: { item_0: 'apple', item_1: 'banana', item_2: 'orange' }

组合键与值生成新键

const scores = { math: 90, science: 85, english: 92 }; const detailed = mapKeys(scores, (value, key) => `${key}_score_${value}`); // 结果: { math_score_90: 90, science_score_85: 85, english_score_92: 92 }

null 与 undefined 的边界处理

与 lodash 一致,当传入nullundefined时,mapKeys不会抛错,而是将其视为空对象并返回{}

import { mapKeys } from 'es-toolkit/compat'; mapKeys(null, iteratee); // {} mapKeys(undefined, iteratee); // {}

这一行为在 compat 实现 中有直接体现:函数入口处首先执行if (object == null) return {};的判空短路,该判断覆盖nullundefined两种情况。对应测试见 mapKeys.spec.ts。

参数与返回值约定

参数

参数类型说明
objectArrayLike<T> \| T \| null \| undefined需要转换键的对象或数组。null/undefined视为空对象
iterateeListIteratee<T> \| ObjectIteratee<T>(可选)每个键的转换函数,默认值为identity函数(原样返回输入),即不传时键不变

其中iteratee回调的调用约定为(value, key, object):第一个参数是当前属性的值,第二个参数是当前键(数组场景下为索引),第三个参数是原对象。

返回值

Record<string, T> | Record<string, T[keyof T]>:返回一个带转换后键的新对象,值保持不变。

深入原理:compat 实现与 iteratee 简写机制

compat 版本的mapKeys是一个非常薄的分发层。其核心逻辑只有两步(见 src/compat/object/mapKeys.ts):

  1. 判空:object == null时直接返回{}
  2. 委托:将对象与经过iteratee()转换后的回调一并交给现代版mapKeys执行。

iteratee 简写(shorthand)机制

之所以 compat 版"相对较慢",正是因为它需要额外的iteratee转换过程(这也是原文档警告的原因之一)。与 lodash 相同,compat 层的iteratee参数并不限于函数,还支持多种简写形式,由 src/compat/util/iteratee.ts 中的iteratee()工厂函数统一转换:

  • 函数:原样返回,直接以(value, key, object)调用;
  • 属性名字符串(如'b'):转换为property(value),即取该属性值作为新键;
  • [属性, 值]二元组:转换为matchesProperty(属性匹配判定);
  • 部分对象:转换为matches(对象匹配判定);
  • null/undefined/缺省:转换为identity,即默认保持原键。

这一点有明确的测试佐证。在 mapKeys.spec.ts 中,mapKeys({ a: { b: 'c' } }, 'b')会得到{ c: { b: 'c' } }——这里'b'是属性简写,实际取每个值的b属性(即'c')作为新键。测试还验证了当iterateenullundefined时使用identity的默认行为(见 mapKeys.spec.ts)。

对应的类型定义位于 ListIteratee.ts 与 IterateeShorthand.ts,IterateeShorthand<T>展开为PropertyKey | [PropertyKey, any] | PartialShallow<T>,与 lodash 的简写约定完全对齐。

底层核心实现

无论走 compat 层还是直接使用现代版,真正的键转换逻辑都在 src/object/mapKeys.ts:

export function mapKeys<T extends Record<PropertyKey, any>, K extends PropertyKey>( object: T, getNewKey: (value: T[keyof T], key: ObjectKeys<T>, object: T) => K ): Record<K, T[keyof T]> { const result = {} as Record<K, T[keyof T]>; const keys = Object.keys(object) as Array<ObjectKeys<T>>; 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循环逐个调用getNewKey生成新键,并把原值写入新对象。它不依赖第三方迭代器,也没有多余的兼容分支,这正是现代版更快的直接原因。

为什么文档建议优先使用现代版mapKeys

原文档在开头给出了明确的::: warning提示:compat 版的mapKeys因为要处理null/undefined判空以及iteratee简写转换过程,相对更慢;如果你的代码不需要 lodash 简写语法与边界兼容,应当优先使用 es-toolkit 原生(现代)版本的mapKeys(日文版见 docs/ja/reference/object/mapKeys.md)。

对比两者:

维度es-toolkit/compatmapKeyses-toolkit原生mapKeys
入口import { mapKeys } from 'es-toolkit/compat'import { mapKeys } from 'es-toolkit'
null/undefined 容错返回{}需自行判空
iteratee 简写(字符串/数组/对象)支持(经iteratee()转换)仅支持函数
性能相对较慢(多一层转换与判空)更快、更精简

需要注意的是,compat 层定位是"与 lodash 100% 行为对齐、可直接替换"(见 src/compat/index.ts),因此它在健壮性与性能之间选择了兼容性优先;而原生版追求的是现代 JavaScript 下的极简与高速。实际项目中,全新代码推荐直接使用原生mapKeys;存量 lodash 代码迁移时则先使用es-toolkit/compat版确保行为一致,再按需逐步替换为原生实现。

总结

es-toolkit/compatmapKeys完整继承了 lodash 的语义:通过iteratee只转换键、保留值,支持函数回调与多种简写形式,并对null/undefined安全返回空对象。其实现本质是"判空 + iteratee 转换 + 委托原生实现"的薄封装,底层核心算法是Object.keys+ 单次循环。理解这层包装关系,你就能在 lodash 迁移与性能敏感场景之间做出正确选择,并随时可以通过 compat 源码 与 测试用例 验证其精确行为。

【免费下载链接】es-toolkitA modern JavaScript utility library that's 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 14:56:44

STM32+MQ-7一氧化碳检测系统:从ADC采集到OLED显示与串口上报

简介&#xff1a;一套基于 STM32F10x 系列单片机与 MQ-7 一氧化碳传感器的环境监测项目源代码&#xff0c;面向嵌入式初学者与电子设计爱好者&#xff0c;旨在实现一氧化碳浓度的实时采集、本地显示、超标报警与数据上报。项目中&#xff0c;STM32 通过 ADC 模块读取 MQ-7 输出…

作者头像 李华
网站建设 2026/9/16 14:56:05

ZTP-148SRC1与R7KA8D2KFLCAC非接触测温实战指南

1. 项目概述&#xff1a;非接触式表面温度测量的实战落地路径ZTP-148SRC1 和 R7KA8D2KFLCAC 这两个器件组合&#xff0c;本质上是在构建一个高性价比、可嵌入、免校准的红外热电堆温度传感系统。它不依赖激光测距或光学聚焦镜头&#xff0c;而是通过热电堆传感器直接捕获目标物…

作者头像 李华
网站建设 2026/9/16 14:55:35

OpenMV+STM32智能车闭环控制系统设计与实现

简介&#xff1a;本资源是南京航空航天大学电子设计竞赛校赛‘自动泊车’题目的完整实现方案&#xff0c;面向嵌入式初学者与课程设计、毕设、工程实训学习者&#xff0c;提供从机器视觉识别到运动控制的端到端技术闭环。资源包含基于STM32F103主控的Keil工程&#xff08;含34个…

作者头像 李华
网站建设 2026/9/16 14:55:23

US Economic State Analysis

US Economic State Analysis 【免费下载链接】LifeOS ⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work. 项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS …

作者头像 李华
网站建设 2026/9/16 14:53:59

OpenClaw 跑微信 ClawBot:Kimi2.5 的 Key 用 TaoToken

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

作者头像 李华