Home > Back-end >  map() method mutating the calling Array
map() method mutating the calling Array

Time:10-24

map() can't mutate the calling array, instead it returns a new Array with modified values. But, the following code mutating the original Array, is there any wrong in my understanding?

const arr = [1, 2, 3, 4, 5];
arr.map((num, index, arr1) => {
  return arr1[index] = num * 2;
});
console.log(arr); // [2, 4, 6, 8, 10]
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Well, you're mutating the original array by passing its reference into the callback function inside map() (arr1) and then manually accessing the indices. It will create a new array if you just return the value from that function.

const arr = [1, 2, 3, 4, 5];
const arr1 = arr.map((num) => {
    return num * 2;
});
console.log(arr); // [1, 2, 3, 4, 5]
console.log(arr1); // [2, 4, 6, 8, 10]

CodePudding user response:

The third argument to the callback function of map is the original/source array on which the map is called upon

The arr and arr1 are both same i.e both are referencing on the same array, You can see it by using console.log(arr === arr1). So what ever you operation perform on the arr1, it gonna affect the arr.

const arr = [1, 2, 3, 4, 5];
arr.map((num, index, arr1) => {
  console.log(arr1 === arr);
  return num * 2;
});
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

You can just return num * 2 from the callback function. map internally creates a new array and return it. So you don't have to assign it as

arr1[index] = num * 2

You can also make it one-liner as:

arr.map((num, index, arr1) => num * 2)

const arr = [1, 2, 3, 4, 5];
const result = arr.map((num, index, arr1) => {
  return num * 2;
});
console.log(arr); // [2, 4, 6, 8, 10]
console.log(result); // [2, 4, 6, 8, 10]
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Array.map creates a new array populated with the results of calling a provided function on every element in the calling array.

Here its specifed that you must call or execute a function on every element of calling array.

What is the issue with your code?

You are not actually calling a function, you are instead updating the original array. If you are looking to create a new array by multiplying each node of the element with 2, you should do something like below.

Working Example

const arr = [1, 2, 3, 4, 5];
const newArray = arr.map((nodeFromOriginalArray, indexOfCurrentElement, arrayFromMapCalled) => {
  return nodeFromOriginalArray * 2;
});
console.log(arr);
console.log(newArray);
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Lets debug the paremeters inside the map function.

Here we have provided three arguments.

First argument nodeFromOriginalArray: The current element being processed in the array. This will be each node from your calling array.

Second argument indexOfCurrentElement: The index of the current element being processed in the array. Which means, the index of current element in calling array.

Third argument arrayFromMapCalled: The array map was called upon. This is the array on which the map function is getting executed. Please note, this is the original array. Updating properties inside this array results in updating your calling array. This is what happened in your case.

You should not modify your original array, which is the third parameter. Instead, you should return your node multipled by 2 inside map and assign this to a new array. Updating the third paramater inside the map function will mutate your calling array.

CodePudding user response:

When calling map on an array, you provide a mapper with three arguments, an item in the array, it's index and the array itself (as you've represented in your snippet).

map takes the value returned by the function mapper as the element at the index in a new array returned by the operation.

const arr = [1,2,3,4,5]
const doubled = arr.map(x => x * 2) // [2,4,6,8, 10]

A over simplified implementation of map (without the index and originalArray params) might look like this. Let's assume that instead of being a method on the array instance, it's a function that takes an array and a mapper function.

I would not recommend re-implementing in production code, there's the native implementation as well as several libraries such as lodash and underscore that implement it.

function map(arr, mapper) {
  const result = [];
  for (const item of arr) {
    const resultItem = mapper(item);
    result.push(resultItem);
  }
  return result;
}

function double(x) {
  return x * 2;
}


const doubled = map([1,2,3,4,5,6], double); // [2, 4, 6, 8 ,10, 12]
  • Related