Каков наилучший подход к клонированию свойств объектов при использовании map ()? - PullRequest
3 голосов
/ 29 мая 2019

Я хочу добавить новое свойство (contactDetails.countryName) и назначить значение для вложенного объекта, хранящегося в массиве с именем users, с помощью функции map ().

Недавно я узнал, что должен использовать оператор распространения (...), а затем создать / назначить новое свойство, чтобы избежать изменения моего исходного массива объектов, поэтому я разработал 2 различные реализации дляэто, но я не совсем уверен, что я следую лучшим практикам, которые я хочу достичь относительно семантики и производительности.

Какой, по вашему мнению, наилучший подход для достижения того, что я хочу сделать?

const countries = [
  { id: 3, countryName : "UK" },
  { id: 4, countryName : "Spain" },
  { id: 6, countryName : "Germany"}
];


const users = [
  { id : 1,
    name: "Douglas Camp",
    dateOfBirth: "23-06-1984",
    contactDetails:
      {
        country: 3,
        phone: "7373724997"
      }
  },
  {
    id : 2,
    name: "Martin Stein",
    dateOfBirth: "19-08-1992",
    contactDetails:
      {
        country: 6,
        phone: "3334343434"
      }
  },
];


const usersData = users.map(user=> {

// Version 1 : using spreading operator twice 

const newUser = {
    ...user,
    contactDetails: {
      ...user.contactDetails,
      countryName: countries.find(c=> c.id == user.contactDetails.country).countryName
    }
  };  
  return newUser;
});

// Version 2: copying the original object property and using spread operator only for cloning the nested object properties

const newUser = {
    id: user.id,
    name: user.name,
    dateOfBirth: user.dateOfBirth,
    contactDetails: {
      ...user.contactDetails,
      countryName: countries.find(c=> c.id == user.contactDetails.country).countryName
    }
  };

console.log(users);
console.log(usersData);

Ответы [ 4 ]

1 голос
/ 29 мая 2019

Вот подход, который вы можете рассмотреть:

  • Прежде всего, я бы Array.reduce страны на карту , чтобы выможно получить их через key / value или в этом случае countries.get(key) и избегать фильтрации этого массива каждый раз.

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

  • Вы также можете рассмотреть возможность использования Object.assign

  • Обратите внимание, что оба оператора ... и Object.assign имеют значение приближается мелкий клон .Они не рекурсивно клонируют вложенные объекты / дочерние объекты.Для этого вы можете использовать JSON.stringify и JSON.parse и т. Д.

let countries = [
  { id: 3, countryName : "UK" },
  { id: 4, countryName : "Spain" },
  { id: 6, countryName : "Germany"}
].reduce((r,{id, countryName}) => (r.set(id, countryName), r), new Map()) // reduce with Map

let users = [ { id : 1, name: "Douglas Camp", dateOfBirth: "23-06-1984", contactDetails: { country: 3, phone: "7373724997" } }, { id : 2, name: "Martin Stein", dateOfBirth: "19-08-1992", contactDetails: { country: 6, phone: "3334343434" } }, ];

let accounts = users.map(user => Object.assign({}, user, {  // <-- map through
  contactDetails: { 
   ...user.contactDetails,
   countryName: countries.get(user.contactDetails.country)  // <-- get by key
  }
}))

users[0].id = 2  // <-- modify users
users[0].contactDetails.phone = "00000"

console.log(users, accounts) // <-- no changes to accounts

Обратите внимание, что при обновлении users[0].id и users[0].contactDetails.phone значения учетных записей не обновлялись.

0 голосов
/ 29 мая 2019

Клонирование и объединение MapsSection Как и массивы, карты можно клонировать:

var original = new Map([
  [1, 'one']
]);

var clone = new Map(original);

console.log(clone.get(1)); // one
console.log(original === clone); // false. Useful for shallow comparison
0 голосов
/ 29 мая 2019

Мне лично нравится использовать Версию 1, так как она делает ваш код намного менее избыточным и более легким для чтения.Он также передает все свойства пользователя в newUser.

0 голосов
/ 29 мая 2019

Я обычно использую версию 1, оператор распространения дважды.Я также хотел бы рассмотреть возможность проверки immer , которая позволяет выполнять изменяемые обновления клонированного черновика и обрабатывает его объединение обратно.

const newUser = immer(user, draft => {
  draft.contactDetails.countryName = countries.find(
    c => c.id == user.contactDetails.country).countryName
  )
})

Просто отредактируйте нужное свойство и добавьте его.обрабатывает копирование всего остального.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...