Reputation: 171
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?
Upvotes: 2
Views: 12151
Reputation: 7624
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
foo
or bar
baz
andFurther (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).
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.
Upvotes: 3
Reputation: 50674
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);
Upvotes: 6
Reputation: 138247
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";
Upvotes: 0
Reputation: 371
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?
Upvotes: 0