Методы массивов JavaScript
Изучите основные методы массивов JavaScript с примерами: push, pop, map, filter, reduce, slice, splice, find и новые иммутабельные методы.
Введение
Массивы — одна из наиболее используемых структур данных в JavaScript, и большая часть их мощи заключается во встроенных методах — функциях, которые вызываются на массиве для добавления, удаления, поиска, преобразования или изменения порядка элементов. В этом руководстве рассматриваются методы, которые используются каждый день, объясняется важнейшее различие между методами, которые изменяют исходный массив, и теми, которые возвращают новый массив, и каждый метод демонстрируется на запускаемом примере.
Если вы только знакомитесь с массивами, начните с главы Массивы JavaScript, а затем вернитесь сюда.
Понимание массивов JavaScript
Массив хранит упорядоченный список значений в одной переменной. Значения могут быть любого из типов данных JavaScript — числа, строки, object-ы, даже другие массивы — и размер не нужно определять заранее.
Создание массива
Простейший способ создать массив — использовать синтаксис литерала с квадратными скобками:
let fruits = ["Apple", "Banana", "Cherry"];Это создаёт массив с именем fruits, содержащий три строковых элемента.
Доступ к элементам массива
Доступ к элементам осуществляется по индексу — позиции с отсчётом от нуля, начиная с начала массива:
Свойство length сообщает количество элементов, а at() принимает отрицательные индексы, поэтому at(-1) всегда возвращает последний элемент.
Изменяющие и неизменяющие методы
Прежде чем рассматривать отдельные методы, изучите это различие — оно объясняет большинство ошибок при работе с массивами:
- Изменяющие методы модифицируют массив на месте.
push,pop,shift,unshift,splice,sort,reverseиfill— все они изменяют массив, на котором вызываются. - Неизменяющие методы не затрагивают исходный массив и возвращают новый массив или значение. В эту группу входят
map,filter,slice,concat,reduce,findи более новыеtoSorted/toSpliced/toReversed.
Когда вы передаёте массив между функциями или сохраняете его в состоянии (например, в компоненте React), предпочитайте неизменяющие методы, чтобы не изменить случайно данные, на которые кто-то ещё полагается.
Основные методы массивов
| Метод | Изменяет? | Описание |
|---|---|---|
push() | Да | Добавляет один или несколько элементов в конец; возвращает новую длину. |
pop() | Да | Удаляет последний элемент и возвращает его. |
shift() | Да | Удаляет первый элемент и возвращает его. |
unshift() | Да | Добавляет элементы в начало; возвращает новую длину. |
splice() | Да | Удаляет, заменяет и/или вставляет элементы в любую позицию. |
sort() | Да | Сортирует элементы (по умолчанию в алфавитном порядке). |
reverse() | Да | Меняет порядок элементов на обратный. |
fill() | Да | Перезаписывает диапазон элементов статическим значением. |
slice() | Нет | Возвращает поверхностную копию части массива. |
concat() | Нет | Объединяет массивы и возвращает новый массив. |
map() | Нет | Возвращает новый массив результатов применения функции к каждому элементу. |
filter() | Нет | Возвращает новый массив элементов, прошедших проверку. |
reduce() | Нет | Сводит массив к одному значению. |
forEach() | Нет | Выполняет функцию для каждого элемента (возвращает undefined). |
find() | Нет | Возвращает первый элемент, удовлетворяющий условию. |
findIndex() | Нет | Возвращает индекс первого элемента, удовлетворяющего условию. |
indexOf() | Нет | Возвращает первый индекс значения или -1. |
includes() | Нет | Возвращает true/false в зависимости от наличия значения. |
some() | Нет | true, если хотя бы один элемент проходит проверку. |
every() | Нет | true, если все элементы проходят проверку. |
toSorted() | Нет | Возвращает отсортированную копию (исходный массив не изменяется). |
toSpliced() | Нет | Возвращает копию после splice (исходный массив не изменяется). |
Добавление и удаление элементов
push()
push() добавляет один или несколько элементов в конец массива и возвращает новую длину.
unshift()
unshift() вставляет элементы в начало массива.
pop()
pop() удаляет последний элемент и возвращает его. Вместе с push() он позволяет использовать массив как стек (последним пришёл — первым вышел).
shift()
shift() удаляет первый элемент и возвращает его. Обратите внимание, что shift и unshift медленнее, чем push/pop, потому что каждый оставшийся элемент должен быть переиндексирован.
Поиск элементов
indexOf()
indexOf() возвращает первый индекс значения или -1, если значение не найдено. Он использует строгое равенство, поэтому не может находить object-ы по их содержимому.
includes()
includes() отвечает на более простой вопрос «да/нет»: есть ли это значение в массиве? Это понятнее, чем indexOf(x) !== -1, и в отличие от indexOf он умеет находить NaN.
find() и findIndex()
Когда нужно найти элемент по условию, а не по точному значению, используйте find() (возвращает элемент) или findIndex() (возвращает его индекс). Оба останавливаются на первом совпадении.
some() и every()
some() возвращает true, если хотя бы один элемент проходит проверку; every() возвращает true, только если все элементы проходят её.
Итерация и преобразование
Эти методы принимают функцию обратного вызова и являются основой современного, декларативного JavaScript. Они хорошо сочетаются с паттернами из главы Циклы JavaScript.
forEach()
forEach() запускает функцию один раз для каждого элемента. Он всегда возвращает undefined, поэтому используйте его для побочных эффектов (например, для логирования), а не для построения нового значения.
map()
map() создаёт новый массив путём преобразования каждого элемента. Новый массив всегда имеет ту же длину, что и исходный.
filter()
filter() создаёт новый массив, содержащий только те элементы, для которых функция обратного вызова возвращает истинное значение.
reduce()
reduce() сводит массив к одному значению, последовательно применяя функцию. Функция обратного вызова получает аккумулятор и текущий элемент; второй аргумент reduce — начальное значение аккумулятора.
Эти преобразователи можно объединять в цепочку: сначала map, затем filter, затем reduce — каждый шаг производит входные данные для следующего.
Изменение порядка и нарезка
sort()
sort() сортирует массив на месте. По умолчанию он сравнивает элементы как строки, что даёт неожиданные результаты для чисел — 10 сортируется раньше 2, потому что "10" идёт раньше "2" в алфавитном порядке. Всегда передавайте функцию сравнения при сортировке чисел.
reverse()
reverse() меняет порядок элементов массива на обратный, изменяя его на месте.
slice()
slice(start, end) возвращает поверхностную копию части массива. Индекс end не включается, а исходный массив остаётся нетронутым — что делает slice() удобным способом копирования массива.
splice()
splice(start, deleteCount, ...items) — это универсальный редактор на месте: он может удалять, заменять и вставлять элементы. Здесь он вставляет "Grape" в позицию с индексом 2, ничего не удаляя (deleteCount равен 0).
concat()
concat() объединяет массивы в новый массив, не изменяя исходные. Синтаксис spread ([...a, ...b]) делает то же самое — см. Остаточные параметры и синтаксис spread.
fill()
fill(value, start, end) перезаписывает диапазон элементов статическим значением, изменяя массив на месте.
Иммутабельные (копирующие) методы
Введённые в ES2023, эти методы делают то же самое, что sort, splice и reverse, — но они возвращают новый массив и оставляют исходный нетронутым. Они идеально подходят для состояния, которое нельзя изменять.
toSorted()
toSpliced()
Заключение
Освоение методов массивов JavaScript — один из наиболее значимых навыков в языке: map, filter и reduce заменяют большинство ручных циклов, а знание того, какие методы изменяют массив, а какие копируют, позволяет избежать целого класса ошибок. Продолжайте практиковаться с запускаемыми примерами выше и изучайте связанные темы: основы Массивов JavaScript и синтаксис spread.