Какие данные можно мутировать в JavaScript, а какие нет
Что проверяют
Различаете ли вы неизменяемость значения и невозможность переприсвоить переменную. Следом почти всегда спрашивают, почему во фронтенд-фреймворках состояние обновляют без мутаций и как сделать глубокую копию.
Как отвечать
Примитивы неизменяемы: string, number, bigint, boolean, undefined, symbol, null. Любая операция с ними создаёт новое значение. Присваивание str[0] = "H" в нестрогом режиме молча игнорируется, а в строгом режиме бросает TypeError. Строку «изменить» можно только создав новую.
Мутабельно всё остальное: объекты, массивы, функции, Map, Set, Date. Объект передаётся в функцию по ссылке на него, поэтому функция может изменить объект вызывающего кода.
Что стоит назвать:
const: запрещает переприсвоение переменной, но не изменение объекта.const arr = []; arr.push(1)работает;Object.freeze: запрещает менять, добавлять и удалять свойства, но только на первом уровне. В строгом режиме запись в замороженный объект бросаетTypeError;Object.sealиObject.preventExtensionsмягче;- мутирующие методы массива:
push,pop,shift,unshift,splice,sort,reverse,fill. Неизменяющие аналоги:map,filter,slice,concatи появившиеся в ES2023toSorted,toReversed,toSpliced,with; - копирование: спред
{ ...obj }иObject.assignкопируют поверхностно, вложенные объекты остаются общими. Глубокую копию делаетstructuredClone, но функции он скопировать не может и бросит ошибку.
Зачем это во фронтенде: React сравнивает состояние через Object.is, и если вызвать setState с тем же, но мутированным объектом, перерисовки не будет. Поэтому обновляют через новый объект или через Immer, который встроен в Redux Toolkit.
Где спотыкаются
Говорят, что const делает объект неизменяемым.
Вызывают arr.sort() на массиве из пропсов или состояния, забывая, что sort меняет массив на месте. Нужен toSorted() или копия.
Считают спред глубокой копией, а потом правят вложенный объект в «копии» и ломают исходное состояние.