меню

Работа с массивами — базовая и ежедневная задача для JS-разработчика. Понимание нюансов каждого метода, включая их стоимость и побочные эффекты, напрямую влияет на производительность и надежность кода. Давайте структурируем знания, выходя за рамки простого перечисления.

Мутирующие методы (Mutating Methods)

Эти методы изменяют исходный массив. Важно помнить об этом, чтобы избежать непреднамеренных сайд-эффектов.

push(...items) / unshift(...items)

Добавляют элементы в конец/начало. Возвращают новую длину массива.

	
const arr = [1, 2];
const newLength = arr.push(3); // arr = [1, 2, 3], newLength = 3		
	

Примечание:

  • unshift добавляет все аргументы сразу, а не по одному. Они становятся частью массива в том порядке, в котором переданы.

    			
    arr.unshift(0, -1); // arr = [-1, 0, 1, 2, 3]
    			
    		
  • Критически важно: unshift — дорогой оператор для больших массивов, так как он требует сдвига всех существующих элементов и пересчета их индексов. push работает значительно быстрее, так как просто добавляет элементы в конец.

pop() / shift()

Удаляют и возвращают последний/первый элемент. Если массив пуст, возвращают undefined.

	
const last = arr.pop(); // last = 3, arr = [-1, 0, 1, 2]
const first = arr.shift(); // first = -1, arr = [0, 1, 2]
	

Примечание:

Аналогично unshift, метод shift требует сдвига всех элементов, начиная с индекса 1, влево, что делает его затратным для больших массивов. pop — быстрый.

splice(start[, deleteCount, ...items])

"Швейцарский нож" для работы с массивами. Изменяет массив, начиная с индекса start, удаляя deleteCount элементов и вставляя ...items на их место. Возвращает массив удаленных элементов.

	
const arr = ['a', 'b', 'c', 'd'];
const removed = arr.splice(1, 2, 'X', 'Y');
// arr = ['a', 'X', 'Y', 'd']
// removed = ['b', 'c']
	

Примечание:

  • Отрицательный start отсчитывается с конца.
  • Если deleteCount опущен, удаляет все элементы до конца.
  • Можно использовать для вставки без удаления: arr.splice(2, 0, 'Z');
  • Производительность: Это мутирующий метод, который может быть затратным, так как после точки вставки/удаления требует сдвига оставшихся элементов и пересчета их индексов.

sort([compareFunction])

Сортирует массив на месте. Без функции сравнения преобразует элементы в строки и сортирует лексикографически.

	
const nums = [10, 2, 1];
nums.sort(); // [1, 10, 2] - сюрприз!
nums.sort((a, b) => a - b); // [1, 2, 10] - правильно для чисел
	

Примечание:

  • Для сложных структур используйте явную compareFunction.

    			
    const users = [{name: 'Bob', age: 30}, {name: 'Alice', age: 25}];
    users.sort((a, b) => a.age - b.age); // Сортировка по возрасту
    			
    		
  • Стабильность: Начиная с ES2019, метод sort в JavaScript является стабильным. Это означает, что элементы, сравнение которых приводит к равенству, сохраняют свой исходный относительный порядок.
  • Производительность: Эффективность алгоритма сортировки зависит от браузера (движка), но в большинстве случаев используется высокооптимизированный алгоритм (Timsort в V8).

reverse() / fill(value[, start[, end]])

reverse переворачивает массив. fill заполняет массив одним значением от start до end (не включая).

	
const arr = [1, 2, 3];
arr.fill(0, 1); // [1, 0, 0]
arr.reverse(); // [0, 0, 1]
	

Примечание:

fill отлично подходит для инициализации массивов фиксированной длины.

	
const newArray = new Array(5).fill(0); // [0, 0, 0, 0, 0]
	

Не мутирующие методы (Non-Mutating Methods)

Создают новый массив или возвращают новое значение, не трогая исходный.

concat(...items)

Объединяет массивы. Принимает как массивы, так и простые значения.

	
const arr1 = [1, 2];
const arr2 = [3, 4];
const newArr = arr1.concat(arr2, 5); // [1, 2, 3, 4, 5]
// arr1 и arr2 не изменены
	

Примечание:

В современном JS часто заменяется на Spread Operator:

	
const newArr = [...arr1, ...arr2, 5]; // Аналогичный результат
	

Однако concat может быть чуть более производительным при объединении именно двух массивов, в то время как spread syntax более читаем и универсален.

slice([start[, end]])

Возвращает новый массив, содержащий копию элементов от start до end (не включая). Отрицательные индексы работают с конца.

	
const arr = [10, 20, 30, 40];
const subArr = arr.slice(1, 3); // [20, 30]
const copy = arr.slice(); // Поверхностная копия массива
	

Примечание:

Создает поверхностную копию (shallow copy). Если массив содержит объекты, они не будут клонированы, и в новом массиве будут ссылки на те же объекты.

join([separator])

Склеивает элементы в строку. separator по умолчанию - запятая.

	
['2024', '12', '31'].join('-'); // "2024-12-31"
	

indexOf(item[, from]) / lastIndexOf() / includes(item[, from])

Поиск в массиве. indexOf и lastIndexOf возвращают индекс (или -1), includes — булево значение.

	
const arr = [1, 2, 3, 2, 1];
arr.indexOf(2); // 1
arr.lastIndexOf(2); // 3
arr.includes(4); // false
	

Примечание:

  • Для поиска объектов или NaN эти методы не подходят (используйте find).

    			
    [NaN].indexOf(NaN); // -1 (не находит)
    [NaN].includes(NaN); // true (находит)
    			
    		
  • includes правильно обрабатывает NaN, в отличие от indexOf.
  • Используют строгое сравнение (===).

find(predicate) / findIndex(predicate)

Ищут элемент/индекс с помощью функции-предиката. Возвращают первый удовлетворяющий элемент или его индекс.

	
const users = [{id: 1}, {id: 2}, {id: 1}];
const user = users.find(item => item.id === 1); // {id: 1}
const index = users.findIndex(item => item.id === 1); // 0
	

Примечание:

Предикат-функция вызывается для каждого элемента до тех пор, пока не будет найдено совпадение. Это может быть эффективнее filter, если нужен только первый элемент.

Итерационные методы (Iteration Methods)

Основа функционального программирования в JS. Не меняют исходный массив (кроме forEach, который может изменять элементы, если они мутабельны).

forEach(callback)

Просто выполняет функцию для каждого элемента. Возвращает undefined.

	
['a', 'b', 'c'].forEach((letter, index) => {
    console.log(`${index}: ${letter}`);
});
	

Примечание:

  • Нельзя прервать цикл break или return из колбэка. Для досрочного прерывания используйте обычный for или for..of.
  • В отличие от for, не создает отдельную область видимости для блока, если используется стрелочная функция.

map(callback)

Создает новый массив, применяя функцию к каждому элементу. Размер итогового массива всегда равен исходному.

	
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2); // [2, 4, 6]
	

Примечание:

Всегда возвращает новый массив. Исходный массив не изменяется. Это один из самых часто используемых и полезных методов.

filter(callback)

Создает новый массив со всеми элементами, прошедшими проверку (предикат вернул true).

	
const nums = [1, 2, 3, 4, 5];
const even = nums.filter(n => n % 2 === 0); // [2, 4]
	

Примечание:

Если ни один элемент не подошел, возвращает пустой массив.

reduce(callback[, initialValue]) / reduceRight

Сворачивает массив в одно значение. callback(accumulator, currentItem, index, array).

	
const sum = [1, 2, 3, 4].reduce((acc, curr) => acc + curr, 0); // 10
	

Примечание:

Всегда передавайте initialValue для надежности. Без нее:

  1. acc берется как первый элемент массива.
  2. Итерация стартует со второго элемента.
  3. Вызов на пустом массиве без initialValue выбросит TypeError.

some(callback) / every(callback)

Проверяют, удовлетворяет ли хотя бы один (some) или все (every) элементы условию. Имеют ленивое выполнение (short-circuit).

	
const hasNegative = [1, -2, 3].some(n => n < 0); // true (остановится на -2)
const allPositive = [1, 2, 3].every(n => n > 0); // true
	

Новые методы (ES6+)

flat([depth]) / flatMap(callback)

flat "поднимает" вложенные массивы на указанный depth (по умолчанию 1). flatMap эквивалентен map().flat(1), но более эффективен.

	
const arr = [1, [2, [3]]];
arr.flat(); // [1, 2, [3]]
arr.flat(2); // [1, 2, 3]

const phrases = ['hello world', 'goodbye moon'];
const words = phrases.flatMap(phrase => phrase.split(' '));
// ['hello', 'world', 'goodbye', 'moon']
	

Примечание:

flatMap позволяет отфильтровать элементы на этапе маппинга, возвращая пустой массив для нежелательных элементов.

	
const arr = [1, 2, 3, 4];
const result = arr.flatMap(x => x % 2 === 0 ? [] : [x * 2]);
// [2, 6] (удвоили только нечетные, отфильтровав четные)
	

Array.from(iterable[, mapFn])

Создает массив из массивоподобного или итерируемого объекта (например, NodeList, arguments, String, Set).

	
Array.from('foo'); // ['f', 'o', 'o']
Array.from([1, 2, 3], x => x * x); // [1, 4, 9] // Использование mapFn
	

Примечание:

Второй аргумент mapFn позволяет сначала создать массив, а затем сразу его обработать, что часто эффективнее цепочки Array.from().map().

Array.isArray(value)

Надежная проверка, является ли значение массивом (в отличие от typeof, который для массива возвращает 'object').

	
Array.isArray([]); // true
Array.isArray({}); // false
Array.isArray(Array.prototype); // true (да, это тоже массив!)
	

Заключение

Правильный выбор метода массива — это не только вопрос синтаксиса, но и:

  1. Производительности: Понимание стоимости операций (например, unshift/shift vs push/pop) критично для работы с большими данными.
  2. Иммутабельности: Использование не мутирующих методов делает код предсказуемее, особенно в реактивных фреймворках (React, Vue).
  3. Читаемости: Цепочка map().filter().reduce() часто яснее, чем один большой цикл for, и меньше подвержена ошибкам.

Комбинируйте эти методы, осознавая их внутреннюю работу, чтобы создавать не только мощные и выразительные, но и высокопроизводительные конструкции для обработки данных.

Помощь сайту
ЮMoney:
4100 1180 7209 833
Карта Сбербанк:
2202 2080 6183 7127

Возможно, вам будет интересно

Разрешаем только ввод цифр в поле input

Часто возникает задача запрета ввода не цифровых значений в поле input. В этом материале разберем реализацию данного механизма на JavaScript.

Собственные социальные share-кнопки

Для шаринга в социальных сетях с громоздким исходным кодом, и сложной детальной кастомизацией, решение которое однажды написал неизвестный, но однозначно добрый программист.

Повышение уровня мастерства в JavaScript ES6

Принципы, о которых пойдет речь, являются фундаментальными для этого языка и будут оставаться таковыми независимо от того, какой фреймворк вы используете. Более того, понимание этих концепций окажется бесценным бонусом, когда вы решите изучить или использовать какую-либо популярную библиотеку или фреймворк из арсенала JavaScript.

Выделяем текущий пункт меню отдельным стилем на jQuery

Допустим нужно выделить текущий пункт меню отдельным стилем. Иногда, это сделать просто невозможно (в случае Ajax) или сложно из-за структуры меню и тут нам на помощь приходит JavaScript, а точнее jQuery