Использование некоторых функциональных принципов и использование неизменяемых данных действительно может сделать ваш JavaScript намного лучше и проще для тестирования. Хотя использование неизменяемых данных в JavaScript кажется чем-то действительно сложным, на самом деле это не так уж и сложно, если вы уже используете Babel. И хотя такие библиотеки, как Immutable.js, настоятельно рекомендуются, мы можем начать еще проще.

Babel многое делает за вас, поскольку позволяет использовать все виды JavaScript следующего поколения, или, если быть более точным, ECMAScript 2015. И довольно легко использовать любой конвейер сборки или даже автономный транспайлер, если вы еще не используете конвейер сборки.

Когда вы хотите использовать неизменяемые данные, вам действительно пригодятся функциональные функции массива map() и filter(), а также свойства распространения. Вот несколько примеров для начала.

Изменение свойства объекта

var originalPerson = {
  firstName: 'Maurice',
  lastName: ''
};
var newPerson = {
  ...originalPerson,
  lastName: 'de Beijer'
};
console.log(newPerson);

…originalPerson использует свойства распространения, которые расширяют все свойства. После него идет lastName: «de Beijer», поэтому он отменяет lastName из объекта originalPerson. И в результате получается новый объект.

{
  firstName: "Maurice",
  lastName: "de Beijer"
}

Просто и легко. И поскольку мы никогда не меняем объекты, мы можем заменить ключевое слово var новым ключевым словом const, чтобы указать, что переменные никогда не переназначаются.

const originalPerson = {
  firstName: 'Maurice',
  lastName: ''
};
const newPerson = {
  ...originalPerson,
  lastName: 'de Beijer'
};
console.log(newPerson);

Добавление чего-либо в массив

Обычно при добавлении чего-либо в массив используется либо присваивание, либо функция push(). Но оба просто мутируют существующий массив вместо создания нового. И с чисто функциональным подходом мы не хотим изменять существующий массив, а вместо этого создаем новый. Опять же очень просто, используя свойства спреда.

const originalPeople = [{
  firstName: 'Maurice'
}];
const newPeople = [
  ...originalPeople,
  {firstName: 'Jack'}
];

console.log(newPeople);

В этом случае мы получаем новый массив с двумя объектами:

[{
  firstName: "Maurice"
}, {
  firstName: "Jack"
}]

Удаление чего-либо из массива

Удаление из массива так же просто с помощью функции фильтра массива().

const originalPeople = [{
  firstName: 'Maurice'
}, {
  firstName: 'Jack'
}];
const newPeople = originalPeople
  .filter(p => p.firstName !== 'Jack');
console.log(newPeople);

И мы получаем массив с одним человеком.

[{
  firstName: 'Maurice'
}]

Обновление существующего элемента в массиве

Изменение существующих элементов так же просто, когда мы комбинируем свойства распространения с функцией массива map().

const originalPeople = [{
  firstName: 'Maurice'
}, {
  firstName: 'Jack'
}];
const newPeople = originalPeople.map(p => {
  if (p.firstName !== 'Jack') {
    return p;
  }
 
  return {
    ...p,
    firstName: 'Bill'
  };
});
console.log(newPeople);

И это все, что нужно, чтобы превратить Джека в Билла.

[{
  firstName: "Maurice"
}, {
  firstName: "Bill"
}]

Действительно приятно и легко, и это делает код очень легко читаемым, когда вы знакомы с новыми свойствами распространения.

Первоначально опубликовано на сайте blogs.msmvps.com 14 декабря 2015 г.