Урок по треку JavaScript 7 мин

Объекты и массивы за 7 минут

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

Объекты и массивы встречаются в каждой задаче. На собесе по ним проверяют три вещи: понимаете ли вы ссылки, умеете ли копировать и знаете ли, какие методы меняют исходные данные.

Ссылки

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

const a = { n: 1 };
const b = a;
b.n = 2;
a.n; // 2, это один и тот же объект

Сравнение === для объектов сравнивает ссылки: [1] === [1] это false. Для сравнения по содержимому нужна своя функция deepEqual или сравнение по конкретным полям.

В функцию передаётся копия ссылки: мутация объекта видна снаружи, а присваивание параметру нового объекта нет.

Копирование

Поверхностная копия копирует только верхний уровень, вложенные объекты остаются общими:

const copy1 = { ...user };
const copy2 = Object.assign({}, user);
const arr2 = [...arr];      // или arr.slice(), Array.from(arr)

Глубокая копия:

  • structuredClone(value): встроен в браузеры и Node 17+, копирует вложенность, циклические ссылки, Date, Map, Set, RegExp, типизированные массивы. Не копирует функции (бросит DataCloneError), DOM-узлы, прототипы классов (экземпляр станет простым объектом), геттеры превращает в значения.
  • JSON.parse(JSON.stringify(x)): старый способ. Теряет undefined и функции, Date превращает в строку, Map и Set в {}, падает на циклах.

Обход объекта

const user = { name: 'Аня', age: 30 };
Object.keys(user);    // ['name', 'age']
Object.values(user);  // ['Аня', 30]
Object.entries(user); // [['name', 'Аня'], ['age', 30]]
Object.fromEntries([['a', 1]]); // { a: 1 }

Эти методы берут только собственные перечисляемые строковые ключи. for...in дополнительно обходит унаследованные перечисляемые свойства. Порядок ключей: сначала целочисленные по возрастанию, затем строковые в порядке добавления, затем символы.

Дескрипторы и заморозка

У каждого свойства есть атрибуты writable, enumerable, configurable (или get/set). Их задают через Object.defineProperty.

  • Object.freeze(obj): нельзя добавлять, удалять и менять свойства.
  • Object.seal(obj): нельзя добавлять и удалять, менять можно.
  • Object.preventExtensions(obj): нельзя только добавлять.

Все три поверхностные: вложенные объекты остаются изменяемыми. В строгом режиме запись в замороженный объект бросает TypeError, в нестрогом молча игнорируется.

Мутирующие методы массива

Меняют исходный массив: push, pop, shift, unshift, splice, sort, reverse, fill, copyWithin.

Возвращают новый массив и не трогают исходный: map, filter, slice, concat, flat, flatMap, а также новые toSorted, toReversed, toSpliced, with (ES2023).

Это особенно важно в React и Redux: состояние нельзя мутировать, иначе ссылка не изменится и интерфейс не обновится.

Сортировка

sort() без компаратора приводит элементы к строкам и сравнивает их как строки: [10, 9, 1].sort() даёт [1, 10, 9]. Для чисел: sort((a, b) => a - b). Компаратор возвращает отрицательное число, если a должно идти раньше, положительное, если позже, и 0, если порядок не важен. Сортировка стабильна по спецификации с ES2019.

Поиск и проверки

ЗадачаМетод
Есть ли значениеincludes (находит NaN), indexOf (не находит NaN)
Первый подходящий элементfind, его индекс findIndex
С концаfindLast, findLastIndex
Хоть один / всеsome, every
Все подходящиеfilter

every на пустом массиве возвращает true, some возвращает false.

Создание массивов

Array.from({ length: 3 }, (_, i) => i * 2); // [0, 2, 4]
Array.from(new Set([1, 1, 2]));             // [1, 2]
Array.of(7);                                // [7], а new Array(7) создаст 7 пустых слотов

Частые ошибки

  • Считать spread глубокой копией.
  • sort на массиве из состояния React: мутирует оригинал.
  • Числа сортировать без компаратора.
  • forEach с return в надежде прервать цикл: не прерывает, нужен for...of, some или find.
  • Ждать, что Object.freeze заморозит вложенные объекты.

Что спросят на собесе

  • Чем поверхностная копия отличается от глубокой, как сделать каждую.
  • Какие методы массива мутируют исходный массив.
  • Почему [10, 1, 2].sort() сортирует «неправильно».
  • Чем Object.freeze отличается от const и Object.seal.
  • Как сравнить два объекта по содержимому.

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.

Вопросы модуля (43)