В мире программирования очень мало постоянных вещей. Одно из них - минимальное изменяемое состояние.
Прежде всего давайте разберемся, что такое неизменность. Это то, что нельзя изменить. С точки зрения программирования, давайте поговорим об объекте, возможно, нам нужно изменить объект. Обычно мы изменяем объект напрямую или видоизменяем объект. Но это связано с множеством проблем. Представьте, что к этому объекту обращаются многие модули вашего кода, каждый из которых время от времени изменяется. Было бы кошмаром справляться со всеми этими изменениями состояния на месте.
Можно подумать, что вместо глобального объекта каждый модуль может иметь свой собственный объект, содержащий только те части, которые им нужны. У него тоже есть проблемы, так как части, предназначенные для совместного использования модулями, должны быть реплицированы и синхронизированы между всеми модулями. Это очередной кошмар!
Предлагаемое решение - никогда не изменять глобальный объект. Вместо этого каждый раз, когда модулю необходимо его изменить, они копируют объект, а затем вносят изменения в новый объект. После внесения всех изменений он возвращает новый объект. Что становится нашим новым глобальным объектом.
Мы вызываем этот глобальный объект, это состояние приложения.
Но даже когда мы не работаем с несколькими модулями, всегда рекомендуется, особенно в таком языке, как JavaScript, никогда не изменять объекты, чтобы избежать ошибок.
Библиотеки управления состоянием, такие как redux, основываются на философии, согласно которой состояние никогда не изменяется.
Неизменяемость в JavaScript.
Для начала мы должны понять, что в JavaScript является изменяемым, а что нет.
Примитивные переменные всегда неизменяемы, поскольку они рассматриваются как значения. Таким образом, довольно просто сохранить их неизменность. С массивами и объектами все не так просто. Взгляните на следующий пример.
Видите ли, когда мы пытаемся скопировать a
в b
, полный массив не копируется, а b
содержит ту же ссылку на массив. Итак, любые изменения в b
отражаются обратно в a
. Это не неизменность! .. мы хотим это изменить.
Для этого мы можем это сделать.
С помощью Object.assign
мы даем начальное состояние объекта / массива и то, что мы хотим скопировать в него. Или, какие изменения мы хотим изменить в исходном состоянии (подробнее об этом изменении).
В синтаксисе ES6 мы можем использовать оператор распространения.
В приведенном выше примере ...a
расширяется до 1,2,3
, поэтому b=[1,2,3,4,5]
. Таким образом, значения копируются и неизменность сохраняется.
То же самое и с объектами.
Посмотрите на приведенный выше код. {}
изменяется на значение point
, таким образом мы получаем {x:2}
, а затем к нему применяется изменение {x:6}
, что дает нам {x:6,y:4}
.
{} -> {x:2,y:4} -> {x:6,y:4}
Или с помощью оператора распространения.
Хотя я подробно не обсуждал глубокое копирование объектов. Для этого я рекомендую эту замечательную статью: - https://dassur.ma/things/deep-copy/
Кроме того, для этого есть специальная библиотека под названием immutable.js от Facebook. Вот ссылка: - https://facebook.github.io/immutable-js/
Но производительность ??
Да, глубокое копирование приносит некоторые накладные расходы. Но, как и все хорошее, у него есть и отрицательная сторона. Но потеря производительности незначительна.