
本文介绍一种通用、不可变的 JavaScript 递归处理方案,用于遍历任意深度的对象/数组结构,自动将形如 { en: "xxx" } 的子对象替换为对应 en 键的字符串值,支持多层嵌套与混合数据类型。
本文介绍一种通用、不可变的 javascript 递归处理方案,用于遍历任意深度的对象/数组结构,自动将形如 `{ en: "xxx" }` 的子对象替换为对应 `en` 键的字符串值,支持多层嵌套与混合数据类型。
在实际开发中(尤其是处理国际化(i18n)配置或 CMS 返回的多语言结构时),我们常遇到类似这样的嵌套对象:
{
"name": { "en": "Contact Champion", "fr": "Contacter le Champion" },
"description": { "en": "Initial talk...", "fr": "Entretien initial..." }
}但业务逻辑可能仅需当前语言(如 "en")的纯字符串值。此时,手动逐层取值既脆弱又不可扩展;而仅处理一级深度的函数(如原始 replaceNestedValue)无法应对深层嵌套或数组场景。
✅ 正确解法是采用递归 + 类型分发(type dispatching)策略:对每个值按其类型分别处理——原始值直接返回,数组映射递归,对象则遍历其键值对,并对每个值尝试提取 targetKey(如 "en"),若存在则取其值,否则继续递归。
以下是经过优化、生产就绪的 TypeScript 兼容实现:
const liftTargetKey = <T>(value: T, targetKey: string): T => {
// 情况1:原始值(string/number/boolean/null/undefined)→ 直接返回
if (Object(value) !== value) return value;
// 情况2:数组 → 递归映射每个元素
if (Array.isArray(value)) {
return value.map(item => liftTargetKey(item, targetKey)) as unknown as T;
}
// 情况3:普通对象(排除 Date、RegExp 等内置对象,仅处理 plain object)
if (value && typeof value === 'object' && value.constructor === Object) {
return Object.fromEntries(
Object.entries(value).map(([key, val]) => [
key,
// 若 val 是对象且包含 targetKey(如 { en: "xxx" }),则取 val[targetKey];
// 否则递归处理 val(支持 val 是数组、深层对象等)
typeof val === 'object' && val !== null && targetKey in val
? (val as Record<string, unknown>)[targetKey]
: liftTargetKey(val, targetKey)
])
) as unknown as T;
}
// 其他对象(如 Date、RegExp、Map、Set)保持原样(不递归,避免意外行为)
return value;
};? 使用示例:
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..." } }]⚠️ 注意事项:
- ✅ 完全不可变:所有新对象/数组均为全新引用,原始数据零副作用;
- ✅ 健壮类型处理:显式区分原始值、数组、plain object,避免对
Date、RegExp等误递归; - ⚠️ 键存在性检查严格:使用
'en' in val而非val?.en,防止val = { en: undefined }被错误提取; - ? 可轻松扩展为多语言切换:传入
navigator.language.split('-')[0]动态取zh/fr等; - ? 不修改原型链或使用
JSON.parse(JSON.stringify())等低效/不安全方式。
该函数已通过深度嵌套对象、含数组的混合结构、空值/undefined 边界场景验证,适用于 React/Vue 数据预处理、构建时 i18n 提取、API 响应标准化等典型场景。

















