Javascript .map() on copied array
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?
javascript arrays function ecmascript-6
add a comment |
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?
javascript arrays function ecmascript-6
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
add a comment |
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?
javascript arrays function ecmascript-6
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
javascript arrays function ecmascript-6
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
add a comment |
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
add a comment |
4 Answers
4
active
oldest
votes
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
2
Alsomap
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
Nowworkers
containsoccupations
only ... maybe recommendforEach
orfor..of
instead?
– Jonas Wilms
Dec 29 '18 at 12:49
@JonasWilmsforEach
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
|
show 1 more comment
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
orbar
- 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.
add a comment |
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?
add a comment |
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";
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
2
Alsomap
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
Nowworkers
containsoccupations
only ... maybe recommendforEach
orfor..of
instead?
– Jonas Wilms
Dec 29 '18 at 12:49
@JonasWilmsforEach
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
|
show 1 more comment
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
2
Alsomap
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
Nowworkers
containsoccupations
only ... maybe recommendforEach
orfor..of
instead?
– Jonas Wilms
Dec 29 '18 at 12:49
@JonasWilmsforEach
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
|
show 1 more comment
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
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);
edited Dec 29 '18 at 13:15
answered Dec 29 '18 at 2:32
Nick ParsonsNick Parsons
5,0372721
5,0372721
2
Alsomap
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
Nowworkers
containsoccupations
only ... maybe recommendforEach
orfor..of
instead?
– Jonas Wilms
Dec 29 '18 at 12:49
@JonasWilmsforEach
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
|
show 1 more comment
2
Alsomap
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
Nowworkers
containsoccupations
only ... maybe recommendforEach
orfor..of
instead?
– Jonas Wilms
Dec 29 '18 at 12:49
@JonasWilmsforEach
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
|
show 1 more comment
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
orbar
- 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.
add a comment |
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
orbar
- 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.
add a comment |
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
orbar
- 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.
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
orbar
- 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.
edited Dec 30 '18 at 1:24
community wiki
2 revs, 2 users 97%
try-catch-finally
add a comment |
add a comment |
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?
add a comment |
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?
add a comment |
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?
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?
answered Dec 29 '18 at 2:34
Amal ArujaAmal Aruja
715
715
add a comment |
add a comment |
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";
add a comment |
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";
add a comment |
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";
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";
answered Dec 29 '18 at 13:07
Jonas WilmsJonas Wilms
56.3k42851
56.3k42851
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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