0

If the array is [true, false], and use .map() to iterate it, the array itself is not changed

array.map(item => {
   item = false
})

array is still [true, false]

But if the items of array are object, then the array would be changed Initially, array is [{checked: true}, {checked: false}], and iterate over the map,

array.map(item => {
    item.checked = false
})

then array becomes [{checked: false}, {checked: false}]

can anyone tell me what the difference is between the two?

Benjamin Li
  • 1,687
  • 7
  • 19
  • 30
  • 1
    read [Array#map documentation](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map) ... .map returns a new array, mapped to the values returned from the callback - you are currently using `Array#map` like you would use `Array#forEach` - though, you probably are excused from doing so, some time ago people would do that because Chrome map was significantly faster than forEach (at least it was in the past) – Jaromanda X Feb 15 '17 at 22:46
  • 3
    When an object is passed as an argument to a function, the value passed is a **reference** to the object, not a complete copy of the object. When a *primitive* is passed, however, it *is* a copy that's passed. Setting the value of the parameter to something different in that case has no effect, but using the object reference to access the object does allow you to modify the object; that's just how object references work. – Pointy Feb 15 '17 at 22:46
  • I think this is the use case of [**forEach**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) not [**map**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)! Plus as @Pointy pointed out: objects are passed by reference, if you change that reference the original object will be changed as well! – ibrahim mahrir Feb 15 '17 at 22:50
  • 1
    Technically, JavaScript is [*always* pass-by-value](http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language), but the value passed for an object is a "reference" (or pointer) to the object. – Kevin Ji Feb 15 '17 at 22:50
  • @JaromandaX I tried to use .forEach() instead of .map() in the first example, but the array keeps intact. why? thanks – Benjamin Li Feb 15 '17 at 23:05
  • Because you aren't updating the array item value – Jaromanda X Feb 15 '17 at 23:06
  • @JaromandaX let array = [true, false] array.forEach(item => {item = false}] array is the same – Benjamin Li Feb 15 '17 at 23:12
  • yes, because you are updating `item`, which is a local (to the function) "variable" ... `array.forEach((item, index, array) => {array[index] = false})` will do what you expect – Jaromanda X Feb 15 '17 at 23:15
  • technically, you can remove the `{}` ... `array.forEach((item, index, array) => array[index] = false);` ... see arrow function documentation for explanation – Jaromanda X Feb 15 '17 at 23:19
  • @JaromandaX Excellent. thanks – Benjamin Li Feb 15 '17 at 23:31

4 Answers4

0

Your examples are not the correct usage for .map(). map() returns a new array based on iterating the original one (which it does not alter). You get elements into that new array by returning them and then capturing the overall return value from map().

var newArray = array.map(item => {
    return item === false;
});

The only reason you falsely believed that using objects made .map() work differently is because you were modifying the object's property values, which are stored within the object, but not the array directly.

In your case, you just need to be iterating the array, so you should be using .forEach().

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • will .forEach() create a new array but the original array keeps intact? or will it modify the content of array? – Benjamin Li Feb 15 '17 at 23:03
  • .forEach returns `undefined` ... always ... it will do what you tell it to do in the callback, but modifying the "item" (first argument) will have no effect - modifying a PROPERTY of item will change the property of the item in the original array – Jaromanda X Feb 15 '17 at 23:16
0

Array#map doesn't do what you think it does. It loops through the array and calls the function you passed with each value, and a new array is created with the return values.

For example:

function doAction(str) {
  try {
    const array = JSON.parse(str);
    return JSON.stringify(
      // Pay attention to this line:
      array.map(item => item + 1)
    );
  } catch (e) {
    return 'Error: ' + e;
  }
}
<p>Input an array of numbers then press "Map it!" to double each of them.</p>
<input id="arrayIn" />
<button onclick="arrayOut.value = doAction(arrayIn.value)">Map it!</button>
<input id="arrayOut" disabled />
Piper McCorkle
  • 1,044
  • 13
  • 27
0

.map() returns a new array explanation:

This means that var array is not mutated (or changed at all by map, by a new array is created to hold the mapped values and returned.

Consider this:

var array = [true, false];
var newArray = array.map(item => {
   return item = false;
});
console.log(array);    // logs out [true, false]
console.log(newArray); // logs out [false, false]

In short, it works but you need to use the value returned by .map()


Pineda
  • 7,435
  • 3
  • 30
  • 45
0

In short: JavaScript functions receive variables passed by value, but objects passed by reference.

In your first example, item inside the function body is simply a new reference created on the spot that contains the value of whatever is passed as the item parameter. This means you can do whatever you want with it, the variable outside the function body will not change unless you explicitly set it.

In your second example however, the item inside the function body is a reference to the actual object outside the function passed as parameter. This means that any changes you make to it inside the function will also change the external object referenced by item.

A more thorough explanation on passing variables by value vs by reference can be found in this thread.

Community
  • 1
  • 1
ppajer
  • 3,045
  • 1
  • 15
  • 22