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);