
本文介绍一种通用、不可变的 JavaScript 递归方案,用于遍历任意深度的嵌套对象或数组,自动将形如 { en: "xxx" } 的语言字段提取为字符串值,适用于国际化数据结构的标准化处理。
本文介绍一种通用、不可变的 javascript 递归方案,用于遍历任意深度的嵌套对象或数组,自动将形如 { en: "xxx" } 的语言字段提取为字符串值,适用于国际化数据结构的标准化处理。
在构建多语言应用时,常遇到类似 { name: { en: "Contact Champion", fr: "Contacter le champion" } } 这样的嵌套结构。若需统一转为扁平形式(如 name: "Contact Champion"),仅处理一层的浅拷贝逻辑远远不够——必须采用深度优先、类型感知的递归策略。
以下是一个健壮、纯函数式的解决方案:
const liftTargetKey = (value, targetKey) =>
// 情况1:原始值(string/number/boolean/null/undefined)直接返回
Object(value) !== value ? value
// 情况2:数组 → 递归映射每个元素
: Array.isArray(value) ? value.map(item => liftTargetKey(item, targetKey))
// 情况3:普通对象 → 遍历所有键值对,对值做递归或提取 targetKey
: Object.fromEntries(
Object.entries(value).map(([key, val]) => [
key,
// 若 val 是对象且存在 targetKey(如 val.en),优先取该值;
// 否则递归处理 val(支持深层嵌套,如 { desc: { en: { nested: "text" } } })
typeof val === 'object' && val !== null && targetKey in val
? val[targetKey]
: liftTargetKey(val, targetKey)
])
);✅ 核心特性说明:
- 不可变性:全程不修改原数据,返回全新结构;
-
类型安全:显式区分原始值、数组、对象,避免
null或undefined引发错误; -
灵活目标键:通过
targetKey参数(如"en")可适配任意语言标识符; -
深度兼容:支持多层嵌套(如
tasks.name.en,tasks.description.details.en); -
数组友好:自动递归处理对象数组(如
skills字段虽为字符串数组,但若含对象亦能处理)。
? 使用示例:
const data = [{
"id": "e8546367-d643-4da0-80dc-0980c9935ded",
"offsetSeconds": 86400,
"tasks": {
"id": "contactChampionInitialTalk",
"icon": "0",
"skills": ["skillCommunityManager"],
"name": { "en": "Contact Champion" },
"description": { "en": "Initial talk, agreement on the theme..." }
}
}];
console.log(liftTargetKey(data, "en"));
// 输出:[{ id: "...", offsetSeconds: 86400, tasks: { id: "...", icon: "0", skills: [...], name: "Contact Champion", description: "Initial talk..." } }]⚠️ 注意事项:
- 若某对象同时存在
en和其他语言键(如fr),本方案仅提取en,不会合并或 fallback;如需多语言 fallback 逻辑,应在调用前封装额外策略; -
val[targetKey]优先级高于递归——即当val本身是{ en: "xxx" }时,直接取"xxx",不再深入其内部; - 对于
null值,typeof null === 'object'为真,因此需额外val !== null判断,已内置在代码中。
此方案兼顾简洁性与鲁棒性,可无缝集成至数据预处理、API 响应标准化或 React/Vue 状态初始化流程中。

















