Why would the map method mutate the original array when its initial purpose is to create a new array ?
I have an array of object which I pass to a pure function which in turn maps the given array and return a new one. Then I notice that the original array was also changed.. I understand the concept that Object in Js are passed by reference and all but still cant quite grab why would the implementation of map
would mutate the original array, kinda beats the purpose IMO.
var initialArray = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ];
function doSomething(array) {
// lodash
// return _.map(array, (item) => _.assign(item, {isSelected: true}));
// vanilla
return array.map(function(item) {
item['isSelected'] = true;
return item
});
}
var changedArray = doSomething(initialArray);
console.log('initialArray', initialArray); // [{ name: 'one', isSelected: true }, ...]
console.log('changedArray', changedArray); // [{ name: 'one', isSelected: true }, ...]
console.log(initialArray === changedArray); // false
First Id like to understand why this happens ?
Second Id like to understand how would one map an array without changing the original one ? (ie. doing ._cloneDeep
each time before map
feels wrong)
Thanks in advance !
Ok so from what I understand this is how things just are. I think I might have had higher expectation for some reason, but it is explainable in Js so at least there is some consistency in place.
The most elegant solution I can think of for creating a new array with new members is
return _.map(array, (item) => _.assign({}, ...item, {isSelected: true}));
.map
will create a new array, but the objects inside the array is still referenced.
so when you make changes in the object item
inside .map function, it is referencing the original object in the input array.
one way to fix it is to clone the each object , before you modify it
var initialArray = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ];
function clone(obj) {
if (null == obj || "object" != typeof obj) return obj;
var copy = obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
}
return copy;
}
function doSomething(array) {
// lodash
// return _.map(array, (item) => _.assign(item, {isSelected: true}));
// vanilla
return array.map(function(item) {
var copy = clone(item);
copy['isSelected'] = true;
return copy;
});
}
var changedArray = doSomething(initialArray);
console.log('initialArray', initialArray); // [{ name: 'one'}, ...]
console.log('changedArray', changedArray); // [{ name: 'one', isSelected: true }, ...]
console.log(initialArray === changedArray); // false
Credit : clone function is copied from this post
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With