Массивы
Массив — упорядоченная коллекция элементов с числовыми индексами, начиная с 0.
Зачем нужно
Массивы — основная структура для хранения списков: пользователи, товары, сообщения. Методы массивов (map, filter, reduce) — ключ к функциональному стилю программирования.
Где используется
- Списки данных из API
- DOM-коллекции
- Обработка и трансформация данных
- Очереди и стеки
- Аргументы функций
Предпосылки
Создание массивов
// Литерал (основной способ)
const fruits = ['яблоко', 'банан', 'вишня'];
// new Array
const empty = new Array(3); // [, , ,] — 3 пустых слота
const filled = new Array(1, 2, 3); // [1, 2, 3]
// Array.of — без подвоха с одним аргументом
Array.of(3); // [3] (не 3 пустых!)
Array.of(1, 2, 3); // [1, 2, 3]
// Array.from — из итерируемого
Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
Array.from({ length: 3 }); // [undefined, undefined, undefined]
Array.from({ length: 5 }, (_, i) => i * 2); // [0, 2, 4, 6, 8]
// Spread
const copy = [...fruits];
Доступ и модификация
const arr = ['a', 'b', 'c', 'd', 'e'];
// Чтение
arr[0]; // 'a'
arr.at(-1); // 'e' (ES2022, с конца)
arr.at(-2); // 'd'
// Запись
arr[1] = 'B';
arr[10] = 'z'; // Создаёт «дыры» — arr.length станет 11
// Длина
arr.length; // количество элементов
arr.length = 2; // Обрезает массив до ['a', 'B']
Методы мутирующие (изменяют оригинал)
const arr = [1, 2, 3];
// Добавление/удаление с конца
arr.push(4); // [1, 2, 3, 4] — возвращает новую длину
arr.pop(); // [1, 2, 3] — возвращает удалённый элемент
// Добавление/удаление с начала
arr.unshift(0); // [0, 1, 2, 3] — возвращает новую длину
arr.shift(); // [1, 2, 3] — возвращает удалённый элемент
// splice — универсальный: удаление, вставка, замена
const items = ['a', 'b', 'c', 'd', 'e'];
items.splice(1, 2); // удалить 2 элемента с индекса 1 → ['a', 'd', 'e']
items.splice(1, 0, 'x', 'y'); // вставить на индекс 1 → ['a', 'x', 'y', 'd', 'e']
items.splice(0, 1, 'A'); // заменить первый → ['A', 'x', 'y', 'd', 'e']
// Сортировка
[3, 1, 2].sort(); // [1, 2, 3]
['банан', 'яблоко', 'вишня'].sort(); // по алфавиту
[10, 2, 30].sort(); // [10, 2, 30] — строковая!
[10, 2, 30].sort((a, b) => a - b); // [2, 10, 30] — числовая
// reverse
[1, 2, 3].reverse(); // [3, 2, 1]
// fill
new Array(5).fill(0); // [0, 0, 0, 0, 0]
[1, 2, 3].fill('x', 1, 2); // [1, 'x', 3]
Методы НЕмутирующие (возвращают новый массив)
map — трансформация каждого элемента
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
// [2, 4, 6, 8, 10]
const users = [{ name: 'Алиса' }, { name: 'Боб' }];
const names = users.map(u => u.name);
// ['Алиса', 'Боб']
filter — отбор по условию
const numbers = [1, 2, 3, 4, 5, 6];
const even = numbers.filter(n => n % 2 === 0);
// [2, 4, 6]
const adults = users.filter(u => u.age >= 18);
reduce — свёртка в одно значение
const numbers = [1, 2, 3, 4, 5];
// Сумма
const sum = numbers.reduce((acc, n) => acc + n, 0); // 15
// Подсчёт вхождений
const words = ['да', 'нет', 'да', 'да', 'нет'];
const count = words.reduce((acc, word) => {
acc[word] = (acc[word] || 0) + 1;
return acc;
}, {});
// { да: 3, нет: 2 }
// Группировка
const people = [
{ name: 'Алиса', dept: 'IT' },
{ name: 'Боб', dept: 'HR' },
{ name: 'Чарли', dept: 'IT' }
];
const grouped = people.reduce((acc, person) => {
(acc[person.dept] ??= ).push(person);
return acc;
}, {});
find / findIndex / findLast
const users = [
{ id: 1, name: 'Алиса' },
{ id: 2, name: 'Боб' },
{ id: 3, name: 'Чарли' }
];
users.find(u => u.id === 2); // { id: 2, name: 'Боб' }
users.findIndex(u => u.id === 2); // 1
users.find(u => u.id === 99); // undefined
users.findLast(u => u.id < 3); // { id: 2, name: 'Боб' } (ES2023)
slice — подмассив
const arr = [0, 1, 2, 3, 4];
arr.slice(1, 3); // [1, 2]
arr.slice(-2); // [3, 4]
arr.slice; // [0, 1, 2, 3, 4] — поверхностная копия
concat, flat, flatMap
[1, 2].concat([3, 4]); // [1, 2, 3, 4]
[1, [2, [3]]].flat(); // [1, 2, [3]]
[1, [2, [3]]].flat(Infinity); // [1, 2, 3]
// flatMap = map + flat(1)
['Привет мир', 'Как дела'].flatMap(s => s.split(' '));
// ['Привет', 'мир', 'Как', 'дела']
Новые иммутабельные методы (ES2023)
const arr = [3, 1, 2];
arr.toSorted((a, b) => a - b); // [1, 2, 3] — arr не изменён
arr.toReversed; // [2, 1, 3] — arr не изменён
arr.toSpliced(1, 1, 99); // [3, 99, 2] — arr не изменён
arr.with(0, 'X'); // ['X', 1, 2] — arr не изменён
Проверки
const arr = [1, 2, 3, 4, 5];
arr.includes(3); // true
arr.some(n => n > 4); // true (хотя бы один)
arr.every(n => n > 0); // true (все)
Array.isArray(arr); // true
Array.isArray('not array'); // false
Перебор
const arr = ['a', 'b', 'c'];
// forEach — без возвращаемого значения
arr.forEach((item, index) => {
console.log(`${index}: ${item}`);
});
// for...of — рекомендуется
for (const item of arr) {
console.log(item);
}
// for...of с индексом
for (const [index, item] of arr.entries()) {
console.log(`${index}: ${item}`);
}
// Классический for — когда нужен контроль
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
Деструктуризация массивов
const [first, second, ...rest] = [1, 2, 3, 4, 5];
// first = 1, second = 2, rest = [3, 4, 5]
// Пропуск элементов
const [, , third] = [1, 2, 3]; // third = 3
// Значения по умолчанию
const [a = 10, b = 20] = [1];
// a = 1, b = 20
// Обмен переменных
let x = 1, y = 2;
[x, y] = [y, x]; // x = 2, y = 1
Частые ошибки
1. sort сортирует как строки
[10, 2, 30].sort(); // [10, 2, 30] — неправильно!
[10, 2, 30].sort((a, b) => a - b); // [2, 10, 30] — правильно
2. forEach не поддерживает break/return
// forEach нельзя прервать
[1, 2, 3].forEach(n => {
if (n === 2) return; // Пропустит только текущую итерацию!
});
// Используй for...of для break
for (const n of [1, 2, 3]) {
if (n === 2) break; // Работает
}
3. Мутация в map/filter
// map должен возвращать новое значение, не мутировать
const users = [{ name: 'Алиса', active: false }];
// Плохо:
users.map(u => { u.active = true; return u; }); // мутирует оригинал
// Хорошо:
users.map(u => ({ ...u, active: true })); // новый объект
Практика
- Напиши функцию
unique(arr)— удаляет дубликаты - Напиши
chunk(arr, size)— разбивает массив на группы - Используй
reduceдля подсчёта суммы цен товаров - Отсортируй массив объектов по нескольким полям