You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建通用select()函数实现任意深度对象属性子集提取与实时重命名

实现通用的对象属性提取与重命名函数

这确实是个非常实用的需求——一个能灵活提取任意深度对象属性、同时支持实时重命名的通用工具,不管是处理单个对象还是批量处理数组都能复用。下面我来给你实现这个select()函数,完全匹配你的预期:

完整实现代码

function select(data, config) {
  const result = {};

  // 遍历配置中的每个新属性名与对应路径
  for (const [newPropName, pathArray] of Object.entries(config)) {
    // 沿着路径数组从原数据中逐层取值,可选链避免中间节点不存在报错
    const targetValue = pathArray.reduce((currentObj, key) => {
      return currentObj?.[key];
    }, data);

    // 将值赋值给新的属性名
    result[newPropName] = targetValue;
  }

  return result;
}

函数工作原理

  1. 初始化结果对象:创建一个空对象用于存储最终的属性子集。
  2. 遍历配置项:通过Object.entries(config)把映射配置转换成键值对数组,每个元素对应「新属性名」和「原属性路径数组」。
  3. 逐层提取属性:用reduce遍历路径数组,从原数据对象开始,沿着路径逐步深入嵌套结构。currentObj?.[key]使用可选链操作符,确保如果中间某个节点不存在(比如原数据里没有某个嵌套属性),不会抛出错误,而是返回undefined。
  4. 赋值重命名:把提取到的值赋值给结果对象的新属性名。

验证你的示例

用你提供的测试数据调用函数:

const earthData = {
  distanceFromSun: 149280000,
  continents: {
    asia: {
      area: 44579000,
      population: 4560667108,
      countries: { japan: { temperature: 62.5 } },
    },
    africa: { area: 30370000, population: 1275920972 },
    europe: { area: 10180000, population: 746419440 },
    america: { area: 42549000, population: 964920000 },
    australia: { area: 7690000, population: 25925600 },
    antarctica: { area: 14200000, population: 5000 },
  },
};

const earthDataSubset = select(earthData, {
  distanceFromSun: ['distanceFromSun'],
  asiaPop: ['continents', 'asia', 'population'],
  americaArea: ['continents', 'america', 'area'],
  japanTemp: ['continents', 'asia', 'countries', 'japan', 'temperature'],
});

得到的结果完全符合预期:

{
  distanceFromSun: 149280000,
  asiaPop: 4560667108,
  americaArea: 42549000,
  japanTemp: 62.5
}

批量处理对象数组

正如你期望的那样,这个函数可以直接配合map批量处理对象数组:

const earthData2050 = {
  distanceFromSun: 149280000,
  continents: {
    asia: {
      area: 44579000,
      population: 4560767108,
      countries: { japan: { temperature: 73.6 } },
    },
    africa: { area: 30370000, population: 1275960972 },
    europe: { area: 10180000, population: 746419540 },
    america: { area: 42549000, population: 964910000 },
    australia: { area: 7690000, population: 25928600 },
    antarctica: { area: 14200000, population: 5013 },
  },
};

const myEarthArr = [earthData, earthData2050];

const mappedResult = myEarthArr.map(record => select(record, {
  distanceFromSun: ['distanceFromSun'],
  asiaPop: ['continents', 'asia', 'population'],
  americaArea: ['continents', 'america', 'area'],
  japanTemp: ['continents', 'asia', 'countries', 'japan', 'temperature'],
}));

返回的批量结果和你硬编码实现的完全一致。

额外优化建议

  • 处理不存在的路径:如果原数据中某个路径不存在,函数会给对应新属性赋值undefined。如果你想跳过这类属性,可以在赋值前加判断:
    if (targetValue !== undefined) {
      result[newPropName] = targetValue;
    }
    
  • 支持数组索引:这个函数天然支持路径中包含数组索引,比如路径['users', 0, 'name']可以提取数组第一个元素的name属性。
  • 添加默认值:如果需要给不存在的路径设置默认值,可以修改reduce逻辑:
    const targetValue = pathArray.reduce((currentObj, key) => {
      return currentObj?.[key] ?? '默认值';
    }, data);
    

内容的提问来源于stack exchange,提问作者Emman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:12:31