Я пытаюсь создать новый массив объектов (usersData) с помощью map(), чтобы добавить новое свойство, которому присвоено значение из вторичного массива (страны). Во время моих тестов я заметил, что мой исходный массив объектов (пользователей) был изменен, и к нему было добавлено новое свойство (countryName). То же самое не произошло, когда я использую карту для создания нового массива объектов для стран моего массива. Может ли кто-нибудь сказать мне, что вызывает это, и помочь мне понять, как избежать такого поведения?
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=> {
const newUser = {};
newUser.name = user.name;
newUser.contactDetails = user.contactDetails;
newUser.contactDetails.countryName = "UK";
return newUser;
});
const countriesData = countries.map(country =>
{
const newCountry = {};
newCountry.name = country.countryName;
newCountry.continent = "Europe";
return newCountry;
});
console.info(countries);
console.info(countriesData);
console.info(users);
console.info(usersData);
Я ожидаю, что элементы в массиве пользователей сохранят свою первоначальную структуру, но теперь для свойства contactDetails.countryName установлено значение «Великобритания».
Вы строите новый массив. Это не означает, что вы также строите новое все внутри массива.
Этот:
newUser.contactDetails = user.contactDetails;
повторно использует объект user.contactDetails
из исходного элемента массива, так что это:
newUser.contactDetails.countryName = "UK";
изменяет объект, совместно используемый как новым, так и старым массивом.
Хороший улов; Я предлагаю добавить решение для устранения проблемы (например, используя Object.assign
для клонирования объекта).
На каждой итерации users.map()
user.contactDetails
содержит ссылку на object
, которую вы сохраняете в новом newUser.contactDetails
. Таким образом, оба будут ссылаться на один и тот же объект в памяти. В вашем конкретном случае вы можете решить эту проблему, распространив user.contactDetails
на новый объект (например, способ его клонирования). Но обратите внимание, что это будет работать только для 1-level
глубокого объекта. Вы должны искать deep-cloning
, если ваша структура более сложная.
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 =>
{
const newUser = {};
newUser.name = user.name;
newUser.contactDetails = {...user.contactDetails};
newUser.contactDetails.countryName = "UK";
return newUser;
});
const countriesData = countries.map(country =>
{
const newCountry = {};
newCountry.name = country.countryName;
newCountry.continent = "Europe";
return newCountry;
});
console.info("countries:", countries);
console.info("countriesData:",countriesData);
console.info("users:", users);
console.info("usersData:", usersData);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Спасибо вам большое за ваш ответ. Я предполагаю, что это происходит только с массивом вложенных объектов, поскольку у меня не было такого же результата при использовании map() для итерации стран. Я прав?
Это произойдет, когда вы скопируете ссылку на тип непримитивный в другую переменную. Вы можете прочитать следующую ссылку для получения дополнительной информации: codeburst.io/…
вы мутируете исходные данные.