Изменчивое состояние в JavaScript | OTUS
⚡ Открываем подписку на курсы!
Проходите параллельно 3 онлайн-курса в месяц по цене одного.
Подробнее

Курсы

Программирование
Flutter Mobile Developer Подготовка к сертификации Oracle Java Programmer (OCAJP)
-8%
Алгоритмы и структуры данных
-12%
Web-разработчик на Python
-11%
Архитектура и шаблоны проектирования
-14%
JavaScript Developer. Basic Супер-интенсив «СУБД в высоконагруженных системах»
-18%
iOS-разработчик. Базовый курс
-23%
Разработчик на Spring Framework
-23%
Python Developer. Basic
-16%
C# ASP.NET Core разработчик
-18%
Разработчик программных роботов (RPA) на базе UiPath и PIX
-6%
JavaScript Developer. Professional
-9%
Android Developer. Basic
-10%
Java Developer. Professional Разработчик C# AWS для разработчиков Highload Architect Reverse-Engineering. Professional CI/CD Vue.js разработчик Agile Project Manager Нереляционные базы данных Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Advanced Fullstack JavaScript developer
Инфраструктура
PostgreSQL
-10%
IoT-разработчик
-12%
Administrator Linux. Professional
-11%
Базы данных
-19%
Administrator Linux.Basic
-18%
Супер-интенсив «СУБД в высоконагруженных системах»
-18%
Супер-интенсив "SQL для анализа данных"
-16%
Software Architect
-12%
Сетевой инженер AWS для разработчиков Highload Architect Разработчик голосовых ассистентов и чат-ботов Внедрение и работа в DevSecOps Администратор Linux. Виртуализация и кластеризация Нереляционные базы данных Супер-практикум по использованию и настройке GIT
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Изменчивое состояние в JavaScript

Состоянием называют практически любые временные данные, которые хранятся в памяти, те же переменные либо поля внутри объектов. Изменчивое состояние — один из источников сложности ПО, особенно в сочетании с объектной ориентацией. Но почему изменчивое состояние является такой большой проблемой?

Ограничения человеческого мозга

К сожалению, человеческий мозг довольно плохо работает с состоянием, ведь мы способны одновременно хранить в рабочей памяти лишь около 5 элементов. Программирование с изменяемым состоянием можно сравнить с умственным жонглированием. И если жонглировать 2-мя шарами относительно просто, то 3-мя и более — намного тяжелее. То же самое и с написанием кода. Ваш код станет надёжнее, а вы сами станете работать более продуктивно, если отбросите изменчивое состояние.

О реальных проблемах с изменчивым состоянием

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

const increasePrice = (item, increaseBy) => {
  // Так не делайте никогда
  item.price += increaseBy;

  return item;
};

const oldItem = { price: 10 };

const newItem = increasePrice(oldItem, 3);

// Выводится «newItem.price 13»
console.log('newItem.price', newItem.price);

// Выводится «oldItem.price 13»
// Сюрпрайз!
console.log('oldItem.price', oldItem.price);

Как видите, ошибка очень тонка. Меняя аргументы функции, вы ненароком поменяли стоимость исходного элемента. Если предполагалось, что значение равняется десяти, на деле оно поменялось на 13.

Избежать этого можно, если создавать и возвращать новый объект (неизменность):

const increasePrice = (item, increaseBy) => ({
  ...item,
  price: item.price + increaseBy
});

const oldItem = { price: 10 };

const newItem = increasePrice(oldItem, 3);

// Выводится «newItem.price 13»
console.log('newItem.price', newItem.price);

// Выводится «oldItem.price 10»
// Как и ожидали
console.log('oldItem.price', oldItem.price);

Также учтите, что копирование посредством ES6-оператора «spread» выполнит не глубокую, а поверхностную копию, в результате чего не скопируется ни одно из вложенных свойств. То есть если у товара есть что-то типа item.seller.id, то seller нового товара всё так же будет ссылаться на старый товар.

Осталось посмотреть предлагаемую конфигурацию ESLint:

rules:
  fp/no-mutation: warn
  no-param-reassign: warn

Не применяйте push для массивов

Аналогичные проблемы присущи и изменениям массива с применением методов типа push:

const a = ['apple', 'orange'];
const b = a;

a.push('microsoft')

// ['apple', 'orange', 'microsoft']
console.log(a);

// ['apple', 'orange', 'microsoft']
// Сюрпрайз!
console.log(b);

Неожиданно, ведь вы, скорее всего, ожидали, что массив b останется прежним. Данной ошибки можно относительно просто избежать, если вы создадите вместо вызова push новый массив.

const newArray = [...a, 'microsoft'];

Источник

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться