почему карта js в массиве изменяет исходный массив?

Я довольно смущен поведением map ().

у меня есть массив объектов, как это :

const products = [{
    ...,
    'productType' = 'premium',
    ...
}, ...]

и я передаю этот массив функции, которая должна возвращать тот же массив, но со всем свободным продуктом:

[{
    ...,
    'productType' = 'free',
    ...
}, ...]

функции :

const freeProduct = function(products){
    return products.map(x => x.productType = "free")
}

который возвращает следующий массив :

["free", "free", ...]

поэтому я переписал свою функцию так:

const freeProduct = function(products){
    return products.map(x => {x.productType = "free"; return x})
}

который возвращает массив как предназначенный.

но ! И это тот момент, когда я теряю рассудок, в обоих случаях мой оригинальный массив продуктов модифицируется.

документация вокруг map () говорит, что она не должна ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map ).

Я даже пытался создать клон моего массива, поворачивая мою функцию так

const freeProduct = function(products){
    p = products.splice()
    return p.map(x => {x.productType = "free"; return x})
}

но я все равно получаю тот же результат (который начинает меня вести сумасшедший.)

Я был бы очень благодарен тому, кто сможет объяснить мне, что я делаю неправильно !

спасибо

2 ответов


вы не изменяете исходный массив. Вы изменяете объекты в массиве. Если вы хотите избежать мутирования объектов в массиве, вы можете использовать Object.assign создать новый объект со свойствами оригинала плюс любые изменения необходимо:

const freeProduct = function(products) {
  return products.map(x => {
    return Object.assign({}, x, {
      productType: "free"
    });
  });
};

2018 Edit:

на большинство браузеров теперь вы можете использовать синтаксис распространения объектов вместо Object.assign для этого:

const freeProduct = function(products) {
  return products.map(x => {
    return {
      ...x,
      productType: "free"
    };
  });
};

чтобы уточнить ответ SimpleJ - если бы вы были === два массива, вы бы обнаружили, что они не будут равны (не тот же адрес в памяти), подтверждая, что сопоставленный массив на самом деле является новым массивом. Проблема в том, что вы возвращаете новый массив, который полон ссылок на те же объекты в исходном массиве (он не возвращает новые объектные литералы, он возвращает ссылки на тот же объект). Поэтому вам нужно создавать новые объекты, которые являются копиями старых объектов-ie, w/ объект.назначить примеру SimpleJ.