Расширенный синтаксис для сложных объектов

#javascript #spread-syntax #ecmascript-2018

#javascript #расширенный синтаксис #ecmascript-2018

Вопрос:

Предположим, у меня есть объект, подобный этому

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

Я хочу воспользоваться синтаксисом распространения, чтобы вернуть клон этого объекта, где store.errors.p1 является новым объектом. Является ли следующий самый простой способ?

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

Комментарии:

1. Да, это так. —

2. @x539, нет, это не так, распространение и скобки вокруг errors могут быть удалены

3. @jo_va ваше право, должно быть, наблюдал за этим

Ответ №1:

Нет, это не самый простой синтаксис для клонирования вашего хранилища и глубокой копии 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))  

Ответ №2:

Вы также можете использовать что-то вроде 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})
  

Ответ №3:

Если вы чувствуете, что это не читается, вы можете использовать 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
};