简体   繁体   中英

why map() is mutating original objects in a nested array?

I'm trying to create a new array of objects (usersData) using map() in order to add a new property assigned with a value from a secondary array (countries). During my tests I've noticed that my original array of objects (users) has been modified and the new property (countryName) has been added to it. The same did not happen when I use map to create a new array of objects for my array countries. Could someone tell me what is causing this and help me to understand how to avoid such a behaviour?

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.log(countries);  
console.log(countriesData); 
console.log(users);
console.log(usersData);

I expect the elements in the array users to keep its original structure but it has now the property contactDetails.countryName set to "UK"

On each iteration of users.map() the user.contactDetails holds a reference to an object that you are storing in the new newUser.contactDetails . So both will refer to the same object on memory. On your particular case, you can solve this spreading the user.contactDetails into a new object (like a way of cloning it). But note this will only work for a 1-level deep object. You should search for deep-cloning if your structure is more complicated.

 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.log("countries:", countries); console.log("countriesData:",countriesData); console.log("users:", users); console.log("usersData:", usersData); 
 .as-console {background-color:black !important; color:lime;} .as-console-wrapper {max-height:100% !important; top:0;} 

You're building a new array. That doesn't mean you're building a new everything-inside-the-array too.

This:

newUser.contactDetails = user.contactDetails;

is reusing the user.contactDetails object from the original array element, so this:

newUser.contactDetails.countryName = "UK";

is modifying an object shared between both the new and the old array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM