Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Неизменяемость данных

Неизменяемость (immutability) — подход, при котором данные не меняют на месте, а создают обновлённую копию. Так проще искать ошибки: объект не может внезапно измениться из-за кода в другом конце программы. На этом подходе построены React и многие другие библиотеки.

Примитивы не меняются

Строки, числа и другие примитивы неизменяемы. Методы строк не трогают исходную строку, а возвращают новую:

const word = 'кот';
const upper = word.toUpperCase();
 
console.log(word); // кот
console.log(upper); // КОТ

Объекты передаются по ссылке

С объектами и массивами иначе. Переменная хранит не сам объект, а ссылку на него, поэтому две переменные могут указывать на один объект:

const anna = { score: 1 };
const player = anna;
 
player.score = 2;
 
console.log(anna.score); // 2

const здесь не помогает: он запрещает записать в переменную другое значение, но не мешает менять содержимое объекта.

Обновление через копию

Вместо изменения создают новый объект с нужными правками. Оператор spread ... копирует старые свойства, а следом пишут новые:

const user = { name: 'Анна', age: 28 };
const older = { ...user, age: 29 };
 
console.log(user.age); // 28
console.log(older.age); // 29

Для массивов так же: [...list, item] вместо list.push(item).

Методы массивов без изменения

Некоторые методы массивов меняют исходный массив. Для них есть пары, которые возвращают копию:

Меняет массивВозвращает копию
sort()toSorted()
reverse()toReversed()
splice()toSpliced()
arr[i] = xarr.with(i, x)
const numbers = [3, 1, 2];
const sorted = numbers.toSorted();
 
console.log(numbers.join(', ')); // 3, 1, 2
console.log(sorted.join(', ')); // 1, 2, 3

Object.freeze

Object.freeze() «замораживает» объект: его свойства больше нельзя изменить, добавить или удалить. Попытка молча игнорируется, а в строгом режиме вызывает ошибку:

const config = Object.freeze({ currency: '€' });
 
config.currency = '$';
 
console.log(config.currency); // €

Заморозка неглубокая

Object.freeze() действует только на верхний уровень: вложенные объекты и массивы остаются изменяемыми. Полную независимую копию со всеми вложенными данными делает функция structuredClone():

const order = { items: ['чай'] };
const copy = structuredClone(order);
 
copy.items.push('кофе');
 
console.log(order.items.length); // 1
console.log(copy.items.length); // 2

Spread копирует тоже только верхний уровень: в копии { ...order } массив items был бы тем же самым.

Частая ошибка

Думать, что sort() возвращает отсортированную копию. Он сортирует сам массив, и исходный порядок теряется:

const prices = [30, 10, 20];
const sorted = prices.sort((a, b) => a - b);
 
console.log(prices.join(', ')); // 10, 20, 30
console.log(sorted === prices); // true

Если исходный массив ещё нужен, используйте toSorted() или сортируйте копию: [...prices].sort().

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.