【问题标题】:Modifying object keys while iterating through nested object迭代嵌套对象时修改对象键
【发布时间】:2020-05-04 04:40:09
【问题描述】:

我想遍历一个嵌套对象并修改每个键(删除第一个字符)。

以下代码遍历整个对象,但不修改键。运行函数后,对象看起来仍然一样。

const removeFirstCharacterOfKey = (obj) => {
    Object.keys(obj).forEach((key) => {
        if (typeof obj[key] === 'object') {
            if(Array.isArray(obj[key])) {
                return;
            }
            return removeFirstCharacterOfKey (obj[key]);
        }
        key = key.substring(1);
    });
}

还可以使用修改后的键创建新对象。有没有可能做到这一点?

【问题讨论】:

  • 这不是那个问题的重复,这里的递归嵌套/转换是一个完全不同的情况

标签: javascript typescript object ecmascript-6


【解决方案1】:

在您当前的代码中,您永远不会改变现有对象(或创建新对象),您只是重新分配 key 参数,这不会有任何副作用。

考虑使用递归Object.fromEntries 映射函数:

const obj = {
  foo: {
    bar: 'val',
    baz: {
      buzz: 'val',
      buzz2: 'val'
    }
  }
};

const objWithSlicedKeys = obj => Object.fromEntries(
  Object.entries(obj).map(
    ([key, val]) => [
      key.slice(1),
      typeof val === 'object' && val !== null ? objWithSlicedKeys(val) : val
    ]
  )
);
console.log(objWithSlicedKeys(obj));

【讨论】:

  • 根据偏好,typeof val === 'object' && val !== null 可以缩短为 val && typeof val === 'object'
【解决方案2】:

https://codesandbox.io/embed/cool-golick-vdf6k?fontsize=14&hidenavigation=1&previewwindow=tests&theme=dark

array.reduce 是您最好的选择。在您的情况下,基本实现将是

function serializer(obj) {
  return Object.entries(obj).reduce((obj, [key, entry]) => ({
      ...obj,
      [key.substr(1)]: entry
    }),{});
}

但是你对数组有一些额外的检查,所以我们需要修改方法以接受自定义修饰符

function serializer(obj, modifier) {
  return Object.entries(obj).reduce(
    (obj, [key, entry]) => ({
      ...obj,
      [modifier(key, entry)]: entry
    }),
    {}
  );
}

并将其用作

const myObj = {
  $a: "hello a",
  $b: "hello b",
  $c: [],
  $d: "hello d",
  $e: "hello e"
};

function serializer(obj, modifier) {
  return Object.entries(obj).reduce(
    (obj, [key, entry]) => ({
      ...obj,
      [modifier(key, entry)]: entry
    }),
    {}
  );
}

const serialized = serializer(myObj, (key, entry) =>
  Array.isArray(entry) ? key : key.substr(1)
);

test("", () => {
  expect(serialized).toEqual({
    a: "hello a",
    b: "hello b",
    $c: [],
    d: "hello d",
    e: "hello e"
  });
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 1970-01-01
    • 2016-05-30
    • 2021-05-19
    • 2023-03-21
    • 1970-01-01
    • 2022-12-20
    相关资源
    最近更新 更多