Js Array.prototype.map() happens to be mutable?
.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
your modifying the object that get's passed by reference to the map function, not the array that get's mapped. Both the changedArray
and the initialArray
contain the same object.
var initialArray = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ];
var initialArray2 = [ { name: 'one' }, { name: 'two' }, { name: 'three'} ];
function doSomething(array) {
// vanilla
return array.map(function(item) {
item['isSelected'] = true;
return item
});
}
function doSomethingElse(array){
return array.map(function( item ){
// return a new object don't change the initial one
return { name: item.name, isSelected: true };
});
}
var changedArray = doSomething(initialArray),
differentObjectsInArray = doSomethingElse( initialArray2 );
console.assert( initialArray !== changedArray, 'both arrays are different' );
console.assert( initialArray[0] !== changedArray[0], 'both arrays are referencing different objects' );
console.assert( initialArray2[0] !== differentObjectsInArray[0], 'both arrays are referencing different objects' );
console.log('initialArray', initialArray );
console.log('initialArray2', initialArray2 );
console.log('differentObjectsInArray', differentObjectsInArray );
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>
With ES6:
let newArray = [...oldArray].map(doStuff);