Javascript: распространять массив объекта в объекте и изменять свойства только внутри него

У меня есть сценарий, в котором я хочу изменить свойства объекта в массиве. Этот массив заключен в другой объект.


const defaultData = {
  title: "Title",
  subtitle: "Subtitle",
  books: [
    {
      bookId: "1",
      imageSrc:
        "any.png",
      name: "Issue",
      userOwnsData: true,
      panelsCollected: 0,
      totalPanels: 123,
      link: "https://google.com",
    },
  ],
  bgColor: "black",
};

Когда я распространяю это так:

{...defaultData, ...defaultData.books[0], panelsCollected:123} //previously it was 0

затем он добавляет еще один дополнительный объект к родительскому объекту, но не обновляет его внутри первого индекса массива книг

Как я могу просто изменить это свойство panelCollected, не нарушая всей структуры, поскольку мы используем машинописный текст.

Редактировать:

Мы также можем изменить его, напрямую обращаясь к свойству, поскольку мы знаем индекс, но это имеет побочный эффект манипулирования исходным набором данных, которого также следует избегать, и нужно обновлять только копию.

Спасибо

Зачем вам нужно распространять этот объект, чтобы обновить одно значение? Почему бы не просто defaultData.books[0].panelsCollected = 123?

Andy 25.11.2022 17:38

@Andy Да, это изменит только одно свойство, но как насчет других данных, которые нам нужны. Как я могу получить ту же структуру с изменением только одного свойства.

Suleman Ahmad 25.11.2022 17:45

Какие еще данные? Вероятно, вам следует расширить код вопроса, чтобы он отражал проблему, с которой вы столкнулись.

Andy 25.11.2022 17:55

@Энди, у меня есть объект с именем defaultData, и я хочу вернуть его ту же структуру, но нужно обновить только одно свойство, которое было panelsCollected. Я старался изо всех сил, чтобы очистить все, о чем идет речь.

Suleman Ahmad 25.11.2022 18:12

Если вы знаете индекс объекта в книгах, вы можете просто обновить значение этого свойства, как я предложил. Вам не обязательно создавать новый объект, распространяя старый.

Andy 25.11.2022 18:16

@ Andy То, что вы упоминаете, имеет побочный эффект, заключающийся в том, что он также будет манипулировать исходным набором данных. При этом мы хотим, чтобы при мутации объектов, как правило, обновлялась только его копия. Вопрос обновлен с большей конкретикой.

Suleman Ahmad 25.11.2022 18:30
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
6
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

При распространении объекта с вложенными свойствами с целью обновления конкретных свойств подумайте об этом в два этапа:

  1. Разверните исходный объект, чтобы скопировать его (...)
  2. Переопределить новые значения свойств после объекта распространения

В вашем примере мы делаем следующее:

  • Дублирование defaultData и назначение обновленного свойства books (будет определено на следующем шаге)
  • Дублирование первой книги (defaultData.books[0]) и присвоение ей обновленного свойства panelsCollected. Затем перезапишите существующее свойство books этим обновленным элементом массива.

Результат выглядит следующим образом:

const defaultData = {
  title: "Title",
  subtitle: "Subtitle",
  books: [
    {
      bookId: "1",
      imageSrc:
        "any.png",
      name: "Issue",
      userOwnsData: true,
      panelsCollected: 0,
      totalPanels: 123,
      link: "https://google.com",
    },
  ],
  bgColor: "black",
};

const newBook = {
  ...defaultData,
  books: [
    {
      ...defaultData.books[0],
      panelsCollected: 123
    }
  ]
}

console.info(newBook)
/*
{
  title: "Title",
  subtitle: "Subtitle",
  books: [
    {
      bookId: "1",
      imageSrc:
        "any.png",
      name: "Issue",
      userOwnsData: true,
      panelsCollected: 123,
      totalPanels: 123,
      link: "https://google.com",
    },
  ],
  bgColor: "black",
};
*/

Если, например, свойство books имеет длину 1000 элементов, вместо этого вам нужно будет найти конкретную книгу в вашем массиве с помощью метода массива (например, find / findIndex) и обновить его, например.

const bookToUpdateIndex = defaultData.books.findIndex(book => book.bookId === '1')

const updatedBooks = [...defaultData.books]
updatedBooks[bookToUpdateIndex] = {
  ...updatedBooks[bookToUpdateIndex],
  panelsCollected: 123
}

const newBook = {
  ...defaultData,
  books: updatedBooks
}
findIndex(book => bookId === '1') должно быть findIndex(book => book.bookId === '1')
Andy 25.11.2022 18:48

А также этот ответ также мутирует исходный объект. @SulemanAhmad, это не то, что ты хотел.

Andy 25.11.2022 18:52

Вместо использования find и синтаксиса расширения альтернативный подход (но не обязательно самый эффективный) может состоять в том, чтобы скопировать объект, преобразовав его в строку, а затем повторно проанализировав эту строку. И тогда вы можете просто обновить объект по нужному вам индексу.

const defaultData = {title:"Title",subtitle:"Subtitle",books:[{bookId:"1",imageSrc:"any.png",name:"Issue",userOwnsData:!0,panelsCollected:0,totalPanels:123,link:"https://google.com"}],bgColor:"black"};

const copy = JSON.parse(JSON.stringify(defaultData));
copy.books[0].panelsCollected = 123;

console.info(defaultData);
console.info(copy);

const newBook ​​= { ...defaultData, books: [ { ...defaultData.books[0], panelCollected: 123 } ] }

Suleman Ahmad 25.11.2022 23:19

Я искал эту часть, которая не мутирует исходный объект.

Suleman Ahmad 25.11.2022 23:20

Но это работает, только если у вас есть одна книга. @СулеманАхмад. Я указывал на вторую часть этого ответа, которая мутировала исходный объект.

Andy 25.11.2022 23:48

Другие вопросы по теме