Javascript .map() on copied array












1















I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:






const employees = [{
name: "John Doe",
age: 41,
occupation: "NYPD",
killCount: 32,
},
{
name: "Sarah Smith",
age: 26,
occupation: "LAPD",
killCount: 12,
},
{
name: "Robert Downey Jr.",
age: 48,
occupation: "Iron Man",
killCount: 653,
},

]

const workers = employees.concat();

workers.map(employee =>
employee.occupation == "Iron Man" ? employee.occupation = "Philantropist" : employee.occupation
);

console.log(employees);





But considering that .concat() created a copy of the original array and assigned it into workers, why does employees get mutated as well?










share|improve this question




















  • 2





    Workers may be a copy of original employees, yet the objects inside are the same references.

    – connexo
    Dec 29 '18 at 2:29











  • Call npm:clone if you need to deep copy something.

    – Paul
    Dec 29 '18 at 2:34








  • 1





    Possible duplicate of why a js map on an array modify the original array?

    – Heretic Monkey
    Dec 29 '18 at 4:05






  • 1





    "I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:" Array.prototype.map always returns an array. It doesn't matter how you use that return value. The statement of yours doesn't make much sense to me.

    – Felix Kling
    Dec 29 '18 at 8:12
















1















I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:






const employees = [{
name: "John Doe",
age: 41,
occupation: "NYPD",
killCount: 32,
},
{
name: "Sarah Smith",
age: 26,
occupation: "LAPD",
killCount: 12,
},
{
name: "Robert Downey Jr.",
age: 48,
occupation: "Iron Man",
killCount: 653,
},

]

const workers = employees.concat();

workers.map(employee =>
employee.occupation == "Iron Man" ? employee.occupation = "Philantropist" : employee.occupation
);

console.log(employees);





But considering that .concat() created a copy of the original array and assigned it into workers, why does employees get mutated as well?










share|improve this question




















  • 2





    Workers may be a copy of original employees, yet the objects inside are the same references.

    – connexo
    Dec 29 '18 at 2:29











  • Call npm:clone if you need to deep copy something.

    – Paul
    Dec 29 '18 at 2:34








  • 1





    Possible duplicate of why a js map on an array modify the original array?

    – Heretic Monkey
    Dec 29 '18 at 4:05






  • 1





    "I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:" Array.prototype.map always returns an array. It doesn't matter how you use that return value. The statement of yours doesn't make much sense to me.

    – Felix Kling
    Dec 29 '18 at 8:12














1












1








1








I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:






const employees = [{
name: "John Doe",
age: 41,
occupation: "NYPD",
killCount: 32,
},
{
name: "Sarah Smith",
age: 26,
occupation: "LAPD",
killCount: 12,
},
{
name: "Robert Downey Jr.",
age: 48,
occupation: "Iron Man",
killCount: 653,
},

]

const workers = employees.concat();

workers.map(employee =>
employee.occupation == "Iron Man" ? employee.occupation = "Philantropist" : employee.occupation
);

console.log(employees);





But considering that .concat() created a copy of the original array and assigned it into workers, why does employees get mutated as well?










share|improve this question
















I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:






const employees = [{
name: "John Doe",
age: 41,
occupation: "NYPD",
killCount: 32,
},
{
name: "Sarah Smith",
age: 26,
occupation: "LAPD",
killCount: 12,
},
{
name: "Robert Downey Jr.",
age: 48,
occupation: "Iron Man",
killCount: 653,
},

]

const workers = employees.concat();

workers.map(employee =>
employee.occupation == "Iron Man" ? employee.occupation = "Philantropist" : employee.occupation
);

console.log(employees);





But considering that .concat() created a copy of the original array and assigned it into workers, why does employees get mutated as well?






const employees = [{
name: "John Doe",
age: 41,
occupation: "NYPD",
killCount: 32,
},
{
name: "Sarah Smith",
age: 26,
occupation: "LAPD",
killCount: 12,
},
{
name: "Robert Downey Jr.",
age: 48,
occupation: "Iron Man",
killCount: 653,
},

]

const workers = employees.concat();

workers.map(employee =>
employee.occupation == "Iron Man" ? employee.occupation = "Philantropist" : employee.occupation
);

console.log(employees);





const employees = [{
name: "John Doe",
age: 41,
occupation: "NYPD",
killCount: 32,
},
{
name: "Sarah Smith",
age: 26,
occupation: "LAPD",
killCount: 12,
},
{
name: "Robert Downey Jr.",
age: 48,
occupation: "Iron Man",
killCount: 653,
},

]

const workers = employees.concat();

workers.map(employee =>
employee.occupation == "Iron Man" ? employee.occupation = "Philantropist" : employee.occupation
);

console.log(employees);






javascript arrays function ecmascript-6






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 29 '18 at 2:31









connexo

21.2k73556




21.2k73556










asked Dec 29 '18 at 2:25









AbbadiahAbbadiah

717




717








  • 2





    Workers may be a copy of original employees, yet the objects inside are the same references.

    – connexo
    Dec 29 '18 at 2:29











  • Call npm:clone if you need to deep copy something.

    – Paul
    Dec 29 '18 at 2:34








  • 1





    Possible duplicate of why a js map on an array modify the original array?

    – Heretic Monkey
    Dec 29 '18 at 4:05






  • 1





    "I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:" Array.prototype.map always returns an array. It doesn't matter how you use that return value. The statement of yours doesn't make much sense to me.

    – Felix Kling
    Dec 29 '18 at 8:12














  • 2





    Workers may be a copy of original employees, yet the objects inside are the same references.

    – connexo
    Dec 29 '18 at 2:29











  • Call npm:clone if you need to deep copy something.

    – Paul
    Dec 29 '18 at 2:34








  • 1





    Possible duplicate of why a js map on an array modify the original array?

    – Heretic Monkey
    Dec 29 '18 at 4:05






  • 1





    "I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:" Array.prototype.map always returns an array. It doesn't matter how you use that return value. The statement of yours doesn't make much sense to me.

    – Felix Kling
    Dec 29 '18 at 8:12








2




2





Workers may be a copy of original employees, yet the objects inside are the same references.

– connexo
Dec 29 '18 at 2:29





Workers may be a copy of original employees, yet the objects inside are the same references.

– connexo
Dec 29 '18 at 2:29













Call npm:clone if you need to deep copy something.

– Paul
Dec 29 '18 at 2:34







Call npm:clone if you need to deep copy something.

– Paul
Dec 29 '18 at 2:34






1




1





Possible duplicate of why a js map on an array modify the original array?

– Heretic Monkey
Dec 29 '18 at 4:05





Possible duplicate of why a js map on an array modify the original array?

– Heretic Monkey
Dec 29 '18 at 4:05




1




1





"I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:" Array.prototype.map always returns an array. It doesn't matter how you use that return value. The statement of yours doesn't make much sense to me.

– Felix Kling
Dec 29 '18 at 8:12





"I have noticed that invoking .map() without assigning it to a variable makes it return the whole array instead of only the changed properties:" Array.prototype.map always returns an array. It doesn't matter how you use that return value. The statement of yours doesn't make much sense to me.

– Felix Kling
Dec 29 '18 at 8:12












4 Answers
4






active

oldest

votes


















1














This is happening because your objects within the array are still being referenced by same pointers. (your array is still referring to the same objects in memory). Also, Array.prototype.map() always returns an array and it's result should be assigned to a variable as it doesn't do in-place mapping. As you are changing the object's properties within your map method, you should consider using .forEach() instead, to modify the properties of the object within the copied employees array. To make a copy of your employees array you can use the following:



const workers = JSON.parse(JSON.stringify(employees));


See example below:




const employees = [
{
name: "John Doe",
age: 41,
occupation: "NYPD",
killCount: 32,
},
{
name: "Sarah Smith",
age: 26,
occupation: "LAPD",
killCount: 12,
},
{
name: "Robert Downey Jr.",
age: 48,
occupation: "Iron Man",
killCount: 653,
},

]


const workers = JSON.parse(JSON.stringify(employees));
workers.forEach(emp => {
if(emp.occupation == "Iron Man") emp.occupation = "Philantropist";
});

console.log("--Employees--")
console.log(employees);
console.log("n--Workers--");
console.log(workers);






  • Note: If your data has any methods within it you need to use another method to deep copy






share|improve this answer





















  • 2





    Also map without mapping makes little sense...

    – Jonas Wilms
    Dec 29 '18 at 12:40











  • @JonasWilms true! Thanks, I've amended my answer

    – Nick Parsons
    Dec 29 '18 at 12:47






  • 1





    Now workers contains occupations only ... maybe recommend forEach or for..of instead?

    – Jonas Wilms
    Dec 29 '18 at 12:49













  • @JonasWilms forEach would be a better approach, I've updated my answer again

    – Nick Parsons
    Dec 29 '18 at 13:16











  • So rather than creating a copy where you have both the containing object (being array) and the actual array values (being literal objects) copied, it only creates a new reference for the containing array? In this case, the example I provided would not have a problem if the array values would have been primitive types, right? For example, employees = ["John Doe", "sarah smith", "Robert Downey Jr."]

    – Abbadiah
    Dec 29 '18 at 17:20





















1














Problem analysis




workers = workers.map(employee => 
employee.occupation == "Iron Man" ? (employee.occupation = "Philantropist", employee) : (employee.occupation, employee)
);


[...] why does employees get mutated as well?




array.map() calls the passed function with each element from the array and returns a new array containing values returned by that function.



Your function just returns the result of the expression



element.baz = condition ? foo : bar;


which, depending on the condition, will




  • evaluate to foo or bar

  • assign that result to baz and

  • return that result


Further (expression1, expression2) will evaluate both expressions and return expression2 (see the comma operator).



So, although you return employee in both cases, you modify the original object with the left expression (expression 1).



Possible solution



You might want to create a new object using Object.assign()



array.map((employee) => Object.assign({ }, employee))


instead of using that array.concat() "trick". Using that mapping, you not only create a new array but also new objects with their attributes copied. Though this would not "deep copy" nested objects like { foo: { ... } } - the object accessible via the property foo would still be the same reference as the original. In such cases you might want to take a look on deep copying modules mentioned in the other answers.






share|improve this answer

































    0














    The array references change but the copied array still reference the original objects in the original array. So any change in the objects in the array are reflected across all copies of the array. Unless you do a deep copy of the array, there is a chance that the some changes in the inner objects get reflected across each copy



    What is the difference between a deep copy and a shallow copy?



    Deep copies can be made in several ways. This post discusses specifically that: What is the most efficient way to deep clone an object in JavaScript?






    share|improve this answer































      0














      map builds up a new array from the values returned from the callback, which caj easily be used to clone the objects in the array:



       const workers = employees.map(employee => ({
      ...employee, // take everything from employee
      occupation: employee.ocupation == "Iron Man" ? "Philantropist" : employee.occupation
      }));


      Or you could deep clone the array, then mutate it with a simple for:



       const workers = JSON.parse(JSON.stringify(workers));
      for(const worker of workers)
      if(worker.ocupation == "Iron Man")
      worker.ocupation = "Philantropist";





      share|improve this answer























        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53966191%2fjavascript-map-on-copied-array%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        1














        This is happening because your objects within the array are still being referenced by same pointers. (your array is still referring to the same objects in memory). Also, Array.prototype.map() always returns an array and it's result should be assigned to a variable as it doesn't do in-place mapping. As you are changing the object's properties within your map method, you should consider using .forEach() instead, to modify the properties of the object within the copied employees array. To make a copy of your employees array you can use the following:



        const workers = JSON.parse(JSON.stringify(employees));


        See example below:




        const employees = [
        {
        name: "John Doe",
        age: 41,
        occupation: "NYPD",
        killCount: 32,
        },
        {
        name: "Sarah Smith",
        age: 26,
        occupation: "LAPD",
        killCount: 12,
        },
        {
        name: "Robert Downey Jr.",
        age: 48,
        occupation: "Iron Man",
        killCount: 653,
        },

        ]


        const workers = JSON.parse(JSON.stringify(employees));
        workers.forEach(emp => {
        if(emp.occupation == "Iron Man") emp.occupation = "Philantropist";
        });

        console.log("--Employees--")
        console.log(employees);
        console.log("n--Workers--");
        console.log(workers);






        • Note: If your data has any methods within it you need to use another method to deep copy






        share|improve this answer





















        • 2





          Also map without mapping makes little sense...

          – Jonas Wilms
          Dec 29 '18 at 12:40











        • @JonasWilms true! Thanks, I've amended my answer

          – Nick Parsons
          Dec 29 '18 at 12:47






        • 1





          Now workers contains occupations only ... maybe recommend forEach or for..of instead?

          – Jonas Wilms
          Dec 29 '18 at 12:49













        • @JonasWilms forEach would be a better approach, I've updated my answer again

          – Nick Parsons
          Dec 29 '18 at 13:16











        • So rather than creating a copy where you have both the containing object (being array) and the actual array values (being literal objects) copied, it only creates a new reference for the containing array? In this case, the example I provided would not have a problem if the array values would have been primitive types, right? For example, employees = ["John Doe", "sarah smith", "Robert Downey Jr."]

          – Abbadiah
          Dec 29 '18 at 17:20


















        1














        This is happening because your objects within the array are still being referenced by same pointers. (your array is still referring to the same objects in memory). Also, Array.prototype.map() always returns an array and it's result should be assigned to a variable as it doesn't do in-place mapping. As you are changing the object's properties within your map method, you should consider using .forEach() instead, to modify the properties of the object within the copied employees array. To make a copy of your employees array you can use the following:



        const workers = JSON.parse(JSON.stringify(employees));


        See example below:




        const employees = [
        {
        name: "John Doe",
        age: 41,
        occupation: "NYPD",
        killCount: 32,
        },
        {
        name: "Sarah Smith",
        age: 26,
        occupation: "LAPD",
        killCount: 12,
        },
        {
        name: "Robert Downey Jr.",
        age: 48,
        occupation: "Iron Man",
        killCount: 653,
        },

        ]


        const workers = JSON.parse(JSON.stringify(employees));
        workers.forEach(emp => {
        if(emp.occupation == "Iron Man") emp.occupation = "Philantropist";
        });

        console.log("--Employees--")
        console.log(employees);
        console.log("n--Workers--");
        console.log(workers);






        • Note: If your data has any methods within it you need to use another method to deep copy






        share|improve this answer





















        • 2





          Also map without mapping makes little sense...

          – Jonas Wilms
          Dec 29 '18 at 12:40











        • @JonasWilms true! Thanks, I've amended my answer

          – Nick Parsons
          Dec 29 '18 at 12:47






        • 1





          Now workers contains occupations only ... maybe recommend forEach or for..of instead?

          – Jonas Wilms
          Dec 29 '18 at 12:49













        • @JonasWilms forEach would be a better approach, I've updated my answer again

          – Nick Parsons
          Dec 29 '18 at 13:16











        • So rather than creating a copy where you have both the containing object (being array) and the actual array values (being literal objects) copied, it only creates a new reference for the containing array? In this case, the example I provided would not have a problem if the array values would have been primitive types, right? For example, employees = ["John Doe", "sarah smith", "Robert Downey Jr."]

          – Abbadiah
          Dec 29 '18 at 17:20
















        1












        1








        1







        This is happening because your objects within the array are still being referenced by same pointers. (your array is still referring to the same objects in memory). Also, Array.prototype.map() always returns an array and it's result should be assigned to a variable as it doesn't do in-place mapping. As you are changing the object's properties within your map method, you should consider using .forEach() instead, to modify the properties of the object within the copied employees array. To make a copy of your employees array you can use the following:



        const workers = JSON.parse(JSON.stringify(employees));


        See example below:




        const employees = [
        {
        name: "John Doe",
        age: 41,
        occupation: "NYPD",
        killCount: 32,
        },
        {
        name: "Sarah Smith",
        age: 26,
        occupation: "LAPD",
        killCount: 12,
        },
        {
        name: "Robert Downey Jr.",
        age: 48,
        occupation: "Iron Man",
        killCount: 653,
        },

        ]


        const workers = JSON.parse(JSON.stringify(employees));
        workers.forEach(emp => {
        if(emp.occupation == "Iron Man") emp.occupation = "Philantropist";
        });

        console.log("--Employees--")
        console.log(employees);
        console.log("n--Workers--");
        console.log(workers);






        • Note: If your data has any methods within it you need to use another method to deep copy






        share|improve this answer















        This is happening because your objects within the array are still being referenced by same pointers. (your array is still referring to the same objects in memory). Also, Array.prototype.map() always returns an array and it's result should be assigned to a variable as it doesn't do in-place mapping. As you are changing the object's properties within your map method, you should consider using .forEach() instead, to modify the properties of the object within the copied employees array. To make a copy of your employees array you can use the following:



        const workers = JSON.parse(JSON.stringify(employees));


        See example below:




        const employees = [
        {
        name: "John Doe",
        age: 41,
        occupation: "NYPD",
        killCount: 32,
        },
        {
        name: "Sarah Smith",
        age: 26,
        occupation: "LAPD",
        killCount: 12,
        },
        {
        name: "Robert Downey Jr.",
        age: 48,
        occupation: "Iron Man",
        killCount: 653,
        },

        ]


        const workers = JSON.parse(JSON.stringify(employees));
        workers.forEach(emp => {
        if(emp.occupation == "Iron Man") emp.occupation = "Philantropist";
        });

        console.log("--Employees--")
        console.log(employees);
        console.log("n--Workers--");
        console.log(workers);






        • Note: If your data has any methods within it you need to use another method to deep copy






        const employees = [
        {
        name: "John Doe",
        age: 41,
        occupation: "NYPD",
        killCount: 32,
        },
        {
        name: "Sarah Smith",
        age: 26,
        occupation: "LAPD",
        killCount: 12,
        },
        {
        name: "Robert Downey Jr.",
        age: 48,
        occupation: "Iron Man",
        killCount: 653,
        },

        ]


        const workers = JSON.parse(JSON.stringify(employees));
        workers.forEach(emp => {
        if(emp.occupation == "Iron Man") emp.occupation = "Philantropist";
        });

        console.log("--Employees--")
        console.log(employees);
        console.log("n--Workers--");
        console.log(workers);





        const employees = [
        {
        name: "John Doe",
        age: 41,
        occupation: "NYPD",
        killCount: 32,
        },
        {
        name: "Sarah Smith",
        age: 26,
        occupation: "LAPD",
        killCount: 12,
        },
        {
        name: "Robert Downey Jr.",
        age: 48,
        occupation: "Iron Man",
        killCount: 653,
        },

        ]


        const workers = JSON.parse(JSON.stringify(employees));
        workers.forEach(emp => {
        if(emp.occupation == "Iron Man") emp.occupation = "Philantropist";
        });

        console.log("--Employees--")
        console.log(employees);
        console.log("n--Workers--");
        console.log(workers);






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 29 '18 at 13:15

























        answered Dec 29 '18 at 2:32









        Nick ParsonsNick Parsons

        5,0372721




        5,0372721








        • 2





          Also map without mapping makes little sense...

          – Jonas Wilms
          Dec 29 '18 at 12:40











        • @JonasWilms true! Thanks, I've amended my answer

          – Nick Parsons
          Dec 29 '18 at 12:47






        • 1





          Now workers contains occupations only ... maybe recommend forEach or for..of instead?

          – Jonas Wilms
          Dec 29 '18 at 12:49













        • @JonasWilms forEach would be a better approach, I've updated my answer again

          – Nick Parsons
          Dec 29 '18 at 13:16











        • So rather than creating a copy where you have both the containing object (being array) and the actual array values (being literal objects) copied, it only creates a new reference for the containing array? In this case, the example I provided would not have a problem if the array values would have been primitive types, right? For example, employees = ["John Doe", "sarah smith", "Robert Downey Jr."]

          – Abbadiah
          Dec 29 '18 at 17:20
















        • 2





          Also map without mapping makes little sense...

          – Jonas Wilms
          Dec 29 '18 at 12:40











        • @JonasWilms true! Thanks, I've amended my answer

          – Nick Parsons
          Dec 29 '18 at 12:47






        • 1





          Now workers contains occupations only ... maybe recommend forEach or for..of instead?

          – Jonas Wilms
          Dec 29 '18 at 12:49













        • @JonasWilms forEach would be a better approach, I've updated my answer again

          – Nick Parsons
          Dec 29 '18 at 13:16











        • So rather than creating a copy where you have both the containing object (being array) and the actual array values (being literal objects) copied, it only creates a new reference for the containing array? In this case, the example I provided would not have a problem if the array values would have been primitive types, right? For example, employees = ["John Doe", "sarah smith", "Robert Downey Jr."]

          – Abbadiah
          Dec 29 '18 at 17:20










        2




        2





        Also map without mapping makes little sense...

        – Jonas Wilms
        Dec 29 '18 at 12:40





        Also map without mapping makes little sense...

        – Jonas Wilms
        Dec 29 '18 at 12:40













        @JonasWilms true! Thanks, I've amended my answer

        – Nick Parsons
        Dec 29 '18 at 12:47





        @JonasWilms true! Thanks, I've amended my answer

        – Nick Parsons
        Dec 29 '18 at 12:47




        1




        1





        Now workers contains occupations only ... maybe recommend forEach or for..of instead?

        – Jonas Wilms
        Dec 29 '18 at 12:49







        Now workers contains occupations only ... maybe recommend forEach or for..of instead?

        – Jonas Wilms
        Dec 29 '18 at 12:49















        @JonasWilms forEach would be a better approach, I've updated my answer again

        – Nick Parsons
        Dec 29 '18 at 13:16





        @JonasWilms forEach would be a better approach, I've updated my answer again

        – Nick Parsons
        Dec 29 '18 at 13:16













        So rather than creating a copy where you have both the containing object (being array) and the actual array values (being literal objects) copied, it only creates a new reference for the containing array? In this case, the example I provided would not have a problem if the array values would have been primitive types, right? For example, employees = ["John Doe", "sarah smith", "Robert Downey Jr."]

        – Abbadiah
        Dec 29 '18 at 17:20







        So rather than creating a copy where you have both the containing object (being array) and the actual array values (being literal objects) copied, it only creates a new reference for the containing array? In this case, the example I provided would not have a problem if the array values would have been primitive types, right? For example, employees = ["John Doe", "sarah smith", "Robert Downey Jr."]

        – Abbadiah
        Dec 29 '18 at 17:20















        1














        Problem analysis




        workers = workers.map(employee => 
        employee.occupation == "Iron Man" ? (employee.occupation = "Philantropist", employee) : (employee.occupation, employee)
        );


        [...] why does employees get mutated as well?




        array.map() calls the passed function with each element from the array and returns a new array containing values returned by that function.



        Your function just returns the result of the expression



        element.baz = condition ? foo : bar;


        which, depending on the condition, will




        • evaluate to foo or bar

        • assign that result to baz and

        • return that result


        Further (expression1, expression2) will evaluate both expressions and return expression2 (see the comma operator).



        So, although you return employee in both cases, you modify the original object with the left expression (expression 1).



        Possible solution



        You might want to create a new object using Object.assign()



        array.map((employee) => Object.assign({ }, employee))


        instead of using that array.concat() "trick". Using that mapping, you not only create a new array but also new objects with their attributes copied. Though this would not "deep copy" nested objects like { foo: { ... } } - the object accessible via the property foo would still be the same reference as the original. In such cases you might want to take a look on deep copying modules mentioned in the other answers.






        share|improve this answer






























          1














          Problem analysis




          workers = workers.map(employee => 
          employee.occupation == "Iron Man" ? (employee.occupation = "Philantropist", employee) : (employee.occupation, employee)
          );


          [...] why does employees get mutated as well?




          array.map() calls the passed function with each element from the array and returns a new array containing values returned by that function.



          Your function just returns the result of the expression



          element.baz = condition ? foo : bar;


          which, depending on the condition, will




          • evaluate to foo or bar

          • assign that result to baz and

          • return that result


          Further (expression1, expression2) will evaluate both expressions and return expression2 (see the comma operator).



          So, although you return employee in both cases, you modify the original object with the left expression (expression 1).



          Possible solution



          You might want to create a new object using Object.assign()



          array.map((employee) => Object.assign({ }, employee))


          instead of using that array.concat() "trick". Using that mapping, you not only create a new array but also new objects with their attributes copied. Though this would not "deep copy" nested objects like { foo: { ... } } - the object accessible via the property foo would still be the same reference as the original. In such cases you might want to take a look on deep copying modules mentioned in the other answers.






          share|improve this answer




























            1












            1








            1







            Problem analysis




            workers = workers.map(employee => 
            employee.occupation == "Iron Man" ? (employee.occupation = "Philantropist", employee) : (employee.occupation, employee)
            );


            [...] why does employees get mutated as well?




            array.map() calls the passed function with each element from the array and returns a new array containing values returned by that function.



            Your function just returns the result of the expression



            element.baz = condition ? foo : bar;


            which, depending on the condition, will




            • evaluate to foo or bar

            • assign that result to baz and

            • return that result


            Further (expression1, expression2) will evaluate both expressions and return expression2 (see the comma operator).



            So, although you return employee in both cases, you modify the original object with the left expression (expression 1).



            Possible solution



            You might want to create a new object using Object.assign()



            array.map((employee) => Object.assign({ }, employee))


            instead of using that array.concat() "trick". Using that mapping, you not only create a new array but also new objects with their attributes copied. Though this would not "deep copy" nested objects like { foo: { ... } } - the object accessible via the property foo would still be the same reference as the original. In such cases you might want to take a look on deep copying modules mentioned in the other answers.






            share|improve this answer















            Problem analysis




            workers = workers.map(employee => 
            employee.occupation == "Iron Man" ? (employee.occupation = "Philantropist", employee) : (employee.occupation, employee)
            );


            [...] why does employees get mutated as well?




            array.map() calls the passed function with each element from the array and returns a new array containing values returned by that function.



            Your function just returns the result of the expression



            element.baz = condition ? foo : bar;


            which, depending on the condition, will




            • evaluate to foo or bar

            • assign that result to baz and

            • return that result


            Further (expression1, expression2) will evaluate both expressions and return expression2 (see the comma operator).



            So, although you return employee in both cases, you modify the original object with the left expression (expression 1).



            Possible solution



            You might want to create a new object using Object.assign()



            array.map((employee) => Object.assign({ }, employee))


            instead of using that array.concat() "trick". Using that mapping, you not only create a new array but also new objects with their attributes copied. Though this would not "deep copy" nested objects like { foo: { ... } } - the object accessible via the property foo would still be the same reference as the original. In such cases you might want to take a look on deep copying modules mentioned in the other answers.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 30 '18 at 1:24


























            community wiki





            2 revs, 2 users 97%
            try-catch-finally
























                0














                The array references change but the copied array still reference the original objects in the original array. So any change in the objects in the array are reflected across all copies of the array. Unless you do a deep copy of the array, there is a chance that the some changes in the inner objects get reflected across each copy



                What is the difference between a deep copy and a shallow copy?



                Deep copies can be made in several ways. This post discusses specifically that: What is the most efficient way to deep clone an object in JavaScript?






                share|improve this answer




























                  0














                  The array references change but the copied array still reference the original objects in the original array. So any change in the objects in the array are reflected across all copies of the array. Unless you do a deep copy of the array, there is a chance that the some changes in the inner objects get reflected across each copy



                  What is the difference between a deep copy and a shallow copy?



                  Deep copies can be made in several ways. This post discusses specifically that: What is the most efficient way to deep clone an object in JavaScript?






                  share|improve this answer


























                    0












                    0








                    0







                    The array references change but the copied array still reference the original objects in the original array. So any change in the objects in the array are reflected across all copies of the array. Unless you do a deep copy of the array, there is a chance that the some changes in the inner objects get reflected across each copy



                    What is the difference between a deep copy and a shallow copy?



                    Deep copies can be made in several ways. This post discusses specifically that: What is the most efficient way to deep clone an object in JavaScript?






                    share|improve this answer













                    The array references change but the copied array still reference the original objects in the original array. So any change in the objects in the array are reflected across all copies of the array. Unless you do a deep copy of the array, there is a chance that the some changes in the inner objects get reflected across each copy



                    What is the difference between a deep copy and a shallow copy?



                    Deep copies can be made in several ways. This post discusses specifically that: What is the most efficient way to deep clone an object in JavaScript?







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Dec 29 '18 at 2:34









                    Amal ArujaAmal Aruja

                    715




                    715























                        0














                        map builds up a new array from the values returned from the callback, which caj easily be used to clone the objects in the array:



                         const workers = employees.map(employee => ({
                        ...employee, // take everything from employee
                        occupation: employee.ocupation == "Iron Man" ? "Philantropist" : employee.occupation
                        }));


                        Or you could deep clone the array, then mutate it with a simple for:



                         const workers = JSON.parse(JSON.stringify(workers));
                        for(const worker of workers)
                        if(worker.ocupation == "Iron Man")
                        worker.ocupation = "Philantropist";





                        share|improve this answer




























                          0














                          map builds up a new array from the values returned from the callback, which caj easily be used to clone the objects in the array:



                           const workers = employees.map(employee => ({
                          ...employee, // take everything from employee
                          occupation: employee.ocupation == "Iron Man" ? "Philantropist" : employee.occupation
                          }));


                          Or you could deep clone the array, then mutate it with a simple for:



                           const workers = JSON.parse(JSON.stringify(workers));
                          for(const worker of workers)
                          if(worker.ocupation == "Iron Man")
                          worker.ocupation = "Philantropist";





                          share|improve this answer


























                            0












                            0








                            0







                            map builds up a new array from the values returned from the callback, which caj easily be used to clone the objects in the array:



                             const workers = employees.map(employee => ({
                            ...employee, // take everything from employee
                            occupation: employee.ocupation == "Iron Man" ? "Philantropist" : employee.occupation
                            }));


                            Or you could deep clone the array, then mutate it with a simple for:



                             const workers = JSON.parse(JSON.stringify(workers));
                            for(const worker of workers)
                            if(worker.ocupation == "Iron Man")
                            worker.ocupation = "Philantropist";





                            share|improve this answer













                            map builds up a new array from the values returned from the callback, which caj easily be used to clone the objects in the array:



                             const workers = employees.map(employee => ({
                            ...employee, // take everything from employee
                            occupation: employee.ocupation == "Iron Man" ? "Philantropist" : employee.occupation
                            }));


                            Or you could deep clone the array, then mutate it with a simple for:



                             const workers = JSON.parse(JSON.stringify(workers));
                            for(const worker of workers)
                            if(worker.ocupation == "Iron Man")
                            worker.ocupation = "Philantropist";






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Dec 29 '18 at 13:07









                            Jonas WilmsJonas Wilms

                            56.3k42851




                            56.3k42851






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53966191%2fjavascript-map-on-copied-array%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Monofisismo

                                Angular Downloading a file using contenturl with Basic Authentication

                                Olmecas