传播复杂对象的语法

问题描述 投票:3回答:3

假设我有一个像这样的对象

let store = {
  "articles": [{...}, {...}, ...],
  "errors": { "p1": { "myNewObject":0 }, "p2": {...}, ...}
}

我想利用Spread syntax返回这个对象的克隆,其中store.errors.p1是一个新对象。以下是最简单的方法吗?

let newStore = { ...store, ...{ errors: { ...store.errors, p1: { "myNewObject":1 } } } }
javascript spread-syntax ecmascript-2018
3个回答
4
投票

不,这不是最简单的语法来克隆您的商店并做一个p1的深层副本,但它非常接近:

let newStore = { ...store, ...{ errors: { ...store.errors, p1: { myNewObject: 1 } } } }
//                         ^^^^                                                     ^
//                           |_______ not necessary ________________________________|

您可以删除errors周围的额外点差和括号。

const store = { articles: [{ a: 1 }], errors: { p1: { myNewObject: 0 }, p2: { a: 1 } } }

const newStore = { ...store, errors: { ...store.errors, p1: { myNewObject: 1 } } }

console.log(JSON.stringify(store))
console.log(JSON.stringify(newStore))

0
投票

你也可以使用lodash.clonedeep这样的东西,然后用store.errors.p1 = { "myNewObject": 1}改变那个属性。

或者如果你愿意,你可以创建一个函数assocIn(灵感来自clojue),它以更惯用的方式实现它:

const assocIn = (obj, [key, ...rest], value) => 
    ({...obj, [key]: rest.length == 0 ? value : assocIn(obj[key], rest, value)});
store = assocIn(store, ['errors', 'p1'], { "myNewObject": 1})

0
投票

如果您认为这是不可读的,那么您可以使用reduce迭代errors对象并首先更新对象,然后使用扩展语法。它可能是更多的代码行,但会为了可读性而抵消。

const updatedkey = "p1";
const updatedData = {
  "myNewObject": 1
};
const store = {
  "articles": [{
    ...
  }, {
    ...
  }],
  "errors": {
    "p1": {
      "myNewObject": 0
    },
    "p2": {
      ...
    },
  }
};
const updatedErrors = Object.keys(store.errors).reduce((acc, key) => {
  const acc[key] = store.errors[key];

  if (key === updatedkey) {
    acc[key] = {
      ...acc[key],
      ...updatedData
    }
  }

  return acc;
}, {});

const newStore = {
  ...store,
  errors: updatedErrors
};
© www.soinside.com 2019 - 2024. All rights reserved.