如何通过遍历路径来访问和编辑对象值?

How to access and edit an object value by iterating on a path?

具有以下数据结构:

const foo = [
    {
        a: 'xxx',
        b: 'xxx',
        c: {
            e: 'xxx',
            ...
        }
    }
    ...
]

是否可以使用此路径对象访问 e 的值

const path = [0, 'c', 'e']

并编辑它?

我试过了

setResponseState(prevState => {
    let data = prevState.responseData
    path.forEach(id => data = data[id])

    data = {}
    return prevState
})

path 是一个上下文值,但我发现 data 是一个副本,因此没有保存在反应状态

谢谢

如果您只想访问该值,您现有的代码大多没问题,您只需要 return 该值。

const foo = [
    {
        a: 'xxx',
        b: 'xxx',
        c: {
            e: 'xxx',
        }
    }
]

const path = [0, 'c', 'e']

function setResponseState(prevState) {
    let data = foo; //prevState.responseData
    path.forEach(id => data = data[id])
    return data;
};

console.log(setResponseState());

如果您修改更新 forEach 中的最后一个值,如下所示应该适用于编辑对象。基本上这避免了覆盖对象引用并只更新值。

const foo = [
  {
    a: "xxx",
    b: "xxx",
    c: {
      e: "xxx",
    },
  },
];


const path = [0, "c", "e"];

setResponseState((prevState) => {
  let data = prevState.responseData;
  path.forEach((id, i) =>
    i === path.length - 1 ? (data[id] = {}) : (data = data[id])
  );
  return prevState;
});

检查这个改变对象的样本

const foo = [
  {
    a: "xxx",
    b: "xxx",
    c: {
      e: "xxx",
    },
  },
];

const path = [0, "c", "e"];


  let data = foo;
  path.forEach((id, i) =>
    i === path.length - 1 ? (data[id] = {}) : (data = data[id])
  );

console.log(foo)

这(通过提供的路径访问嵌套值)是非常有表现力的标准任务 reduce method in collaboration with optional chaining 以确保故障安全实施 ...

const foo = [{
  a: "zzz",
  b: "yyy",
  c: {
    e: "xxx",
  },
}];

console.log({ foo });
console.log(
  '[0, "c", "e"].reduce((value, key) => value?.[key], foo) ...',
  [0, "c", "e"].reduce((value, key) => value?.[key], foo)
);
console.log(
  '[0, "C", "e"].reduce((value, key) => value?.[key], foo) ...',
  [0, "C", "e"].reduce((value, key) => value?.[key], foo)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

如果要改变对象的嵌套 属性,最好在函数中使用上述方法 ...

const foo = [{
  a: "zzz",
  b: "yyy",
  c: {
    e: "xxx",
    f: "uuu",
  },
}];

function assignValueToExistingNestedProperty(type, path, value) {
  const [lastKey, ...keyList] = path.reverse();

  // access the next to last property value.
  const reference = keyList
    .reverse()
    .reduce((value, key) => value?.[key], type);

  Object.assign((reference ?? {}), { [lastKey]: value });

  return type;
}

console.log({ foo });
console.log(
  'assignValueToExistingNestedProperty(foo, [0, "c", "e"], "AAA") ...',
  assignValueToExistingNestedProperty(foo, [0, "c", "e"], "AAA")
);
console.log(
  'assignValueToExistingNestedProperty(foo, [0, "C", "e"], "BBB") ...',
  assignValueToExistingNestedProperty(foo, [0, "C", "e"], "BBB")
);
console.log({ foo });
.as-console-wrapper { min-height: 100%!important; top: 0; }