Reputation: 23161
I've noticed that deleting object properties when using Array.map()
affects the original array, I assume since each iteration's item is still referencing the original array:
var objects = [{name: 'a', password: 'x'}, {name: 'b', password: 'x'}];
var clean = objects.map(user => {delete user.password; return user;});
console.log(JSON.stringify(objects));
> [{"name":"a"},{"name":"b"}]
Is there a way to use map
or filter
without it modifying the original? I can think to loop through each item and create a clone but curious if there's a simpler way.
Upvotes: 3
Views: 3002
Reputation: 6872
This is not a problem with map
or filter
, these methods always return a new array. This is a problem with objects always being passed by reference in Javascript.
Consider the following:
const a = { foo: 1 }
const b = { foo: 2 }
const arr1 = [ a, b ];
const arr2 = arr1.map(v => {
v.foo = 0;
return v;
});
console.log(arr1);
console.log(arr2);
console.log(JSON.stringify(arr1) === JSON.stringify(arr2)) // true
If you want to create a copy of each object in an array while doing a map you could use the spread operator:
const a = { foo: 1 }
const b = { foo: 2 }
const arr1 = [ a, b ];
const arr2 = arr1.map(v => {
return {...v, foo: 0};
});
console.log(arr1);
console.log(arr2);
console.log(JSON.stringify(arr1) === JSON.stringify(arr2)) // false
It's worth noting that the spread operator is a shallow clone, this means that objects within objects will still be passed by reference.
const c = { foo: 3 }
const a = { foo: 1, biz: c }
const b = { foo: 2, biz: c }
const arr1 = [ a, b, c ];
const arr2 = arr1.map(v => {
return {...v, foo: 0};
});
console.log(arr1);
console.log(arr2);
console.log(JSON.stringify(arr1) === JSON.stringify(arr2)) // false
Upvotes: 3
Reputation: 8784
You can map over all of the items and return only the name.
const objectsWithNames = objects.map(({name}) => ({name}));
Upvotes: 1
Reputation: 2454
The original array isn't being modified, but rather the items in the array (the objects) are. Since javascript objects are passed by reference, when you modify the objects in the new array, the references in the old array show the same modifications.
So, as you said, you can loop through each item and create a clone. Of course, you could perform a deep copy of the entire array too.
Upvotes: 0
Reputation: 92440
You can reference everything except password
with dereferencing. Then use map to build a new object with everything else. This is nice if you have other properties on the object other than name
and want to include everything except password
.
var objects = [{name: 'a', password: 'x'}, {name: 'b', password: 'x'}];
var clean = objects.map(({password, ...user}) => user);
console.log(objects); // untouched
console.log(clean); // no password
Upvotes: 4