JavaScript — динамичный и мощный язык, широко используемый в процессе разработки веб-приложений. В этой статье вы узнаете о структурах данных mutable
и immutable
в JavaScript, их важности и использовании.
Неизменяемые структуры данных
Неизменяемые структуры данных — это типы данных, значения которых нельзя изменить. Эти типы создают новое значение вместо изменения существующего значения при назначении нового значения.
Примитивные типы данных
- Нить
- Число
- логический
- Неопределенный
- Нулевой
- BigInt
- Символ
const str = "Hello"; const newStr = str.concat(", World!"); console.log(str); // "Hello" - Original string unchanged console.log(newStr); // "Hello, World!" - A new string is created const num = 5; const newNum = num + 1; console.log(num); // 5 - Original number unchanged console.log(newNum); // 6 - A new number value is created
Изменяемые структуры данных
Типы данных объекта изменяемы. Это означает, что вы можете изменять их свойства и значения, затрагивая все объекты с одной и той же ссылкой.
Объект
- Простой объект
- Множество
- Функция
- Дата
- Специальные структуры, такие как Map, Set, WeakMap, WeakSet
const arr = [1, 2, 3]; arr[1] = 4; console.log(arr); // [1, 4, 3] - Directly modifying the array const obj = { key: "value" }; obj.key = "newValue"; console.log(obj); // { key: "newValue" } - Directly modifying the object
Однако иногда вы можете захотеть использовать изменяемые объекты, как если бы они были неизменяемыми. В этом случае вы можете использовать внешние библиотеки (например, Immutable.js, Immer) или некоторые методы, доступные в самом языке (например, Object.assign, Array.prototype.slice, оператор распространения), чтобы рассматривать изменяемые объекты как неизменяемые.
Например, вы можете использовать оператор распространения для создания нового массива без изменения исходного массива:
const arr = [1, 2, 3]; const newArr = [...arr.slice(0, 1), 4, ...arr.slice(2)]; console.log(newArr); // [1, 4, 3] console.log(arr); // [1, 2, 3] - Original array unchanged
Здесь мы создали новый массив без изменения исходного массива, что позволяет исходным данным вести себя так, как если бы они были неизменяемыми. С помощью этих методов вы можете использовать изменяемые структуры данных более предсказуемым и эффективным способом.
Redux и неизменяемые структуры данных
Redux — это популярная библиотека для управления состоянием в приложениях JavaScript, которая повышает производительность и предсказуемость вашего приложения за счет использования неизменяемых структур данных.
Использование неизменяемых данных в Redux основано на следующих принципах:
- Единственный источник правды: Redux хранит все состояние приложения в одном объекте JavaScript. Это дерево состояний является общим для всех компонентов, и состояние служит единым источником.
- Состояние только для чтения: дерево состояний неизменяемо (не может быть изменено напрямую) и доступно только для чтения. Когда вы хотите внести изменения в состояние, вы отправляете действие в Redux, которое затем используется для обновления состояния.
- Редюсеры: редукторы — это чистые функции, которые выполняют действия и возвращают новое состояние на основе текущего состояния. Вместо прямого изменения существующего состояния редьюсеры всегда возвращают новый объект состояния, придерживаясь принципа неизменности.
Redux обеспечивает использование неизменяемых данных с этими принципами, как показано ниже:
function counterReducer(state = 0, action) { switch (action.type) { case "INCREMENT": return state + 1; // Returning a new numeric value case "DECREMENT": return state - 1; // Returning a new numeric value default: return state; } }
В приведенном выше примере мы не изменяем текущее состояние напрямую. Вместо этого мы создаем новое состояние, возвращая новое числовое значение для операций INCREMENT
и DECREMENT
.
Вот еще один пример Redux для состояния объекта:
function todoReducer(state = {}, action) { switch (action.type) { case "ADD_TODO": return { ...state, [action.id]: { id: action.id, text: action.text, completed: false, }, }; // Updating the state by creating a new object case "TOGGLE_TODO": return { ...state, [action.id]: { ...state[action.id], completed: !state[action.id].completed, }, }; // Updating the state by creating a new object default: return state; } }
В этом примере мы не изменяем исходное состояние напрямую во время операций ADD_TODO
и TOGGLE_TODO
. Вместо этого мы обновляем состояние, создавая новые объекты с помощью оператора распространения (...
).
Заключение
Понимание изменяемых и неизменяемых структур данных в JavaScript и их правильное использование может значительно повысить производительность, надежность и масштабируемость ваших приложений. В этой статье мы рассмотрели основные различия между изменяемыми и неизменяемыми структурами данных и несколько примеров использования этих структур.