Скидка до 55% и 3 курса в подарок 2 дня 13 :30 :09 Выбрать курс
Код Справочник по фронтенду
#статьи

Массивы в JavaScript: основы, методы и примеры кода

Массивный гайд для быстрого погружения.

Иллюстрация: Polina Vari для Skillbox Media

В программировании часто нужно хранить набор значений в одном месте и обращаться к ним по порядку. Для этого в JavaScript используют массивы (Array) — специальный тип объекта для работы с упорядоченными коллекциями данных. В этой статье мы подробно поговорим про массивы, и вы узнаете, как их создавать и использовать. Кроме того, в конце вас ждут несколько несложных задач, с помощью которых вы сможете закрепить изученный материал.

Содержание


Что такое массивы в JavaScript и как их создавать

Массив (Array) в JavaScript — это упорядоченная коллекция элементов, где каждый элемент имеет свой числовой индекс (позицию). Индексация начинается с 0: первый элемент находится по индексу arr[0], второй — arr[1] и так далее. В отличие от многих других языков программирования, массивы в JS могут содержать элементы разных типов: числа, строки, логические значения true или false, объекты, функции и даже другие массивы.

Представьте, что вы хотите сохранить список покупок. Вместо того чтобы создавать переменные для каждого товара, можно использовать массив.

// Без массива неудобно
const item1 = 'молоко';
const item2 = 'хлеб';
const item3 = 'яйца';

// С массивом удобно и компактно
const shoppingList = ['молоко', 'хлеб', 'яйца'];
console.log(shoppingList); // ['молоко', 'хлеб', 'яйца']

// Можно легко добавить новый товар
shoppingList.push('масло');
console.log(shoppingList); // ['молоко', 'хлеб', 'яйца', 'масло']

В JavaScript есть несколько способов создать массив. Самый простой — через квадратные скобки []. Это называется литералом массива. Пустые скобки создают пустой массив, а если добавить внутрь какие-то данные — получится массив с элементами.

// Пустой массив
const arr = [];
console.log(arr); // []

// Массив из трёх строк
const animals = ['cat', 'dog', 'mouse'];
console.log(animals); // ['cat', 'dog', 'mouse']

Есть и другой способ создать массив — вызвать конструктор Array (обычно через new Array(…)). Здесь важно помнить, что у него два режима работы: если передать одно число, оно будет воспринято как длина массива, и элементы при этом не заполняются значением undefined — создаются пустые слоты; а если передать несколько значений, они станут элементами массива — например, new Array(1, 2, 3) создаст массив из трёх чисел.

// Массив из трёх пустых элементов
const emptyArray = new Array(3);
console.log(emptyArray); // [empty × 3]

// Массив из перечисленных элементов
const numsArray = new Array(1, 2, 3);
console.log(numsArray); // [1, 2, 3]

Кроме литерала [] и конструктора Array() есть методы Array.of() и Array.from(). Они помогают создавать массивы и преобразовывать другие значения в массивы.

Метод Array.of() создаёт массив из всех переданных значений. Он работает предсказуемее, чем Array():

const objs = Array.of(3, 'c', 'dfds');
console.log(objs); // [3, 'c', 'dfds']

Метод Array.from() преобразует строку и другие итерируемые значения в массив. Если вторым аргументом передать функцию, она сразу обработает каждый элемент.

// Превращаем строку в массив символов
const charArr = Array.from('hello');
console.log(charArr); // ['h', 'e', 'l', 'l', 'o']

// Превращаем каждый символ строки в массив чисел
const numArr = Array.from('12345', Number);
console.log(numArr); // [1, 2, 3, 4, 5]

Что такое length и как обращаться к элементам массива

Массив хранит элементы по порядку, и у каждого свой номер — индекс. Нумерация начинается с нуля: первый элемент находится под индексом 0, второй — под индексом 1 и так далее.

const items = ['item01', 'item02', 'item03'];
console.log(items[0]); // item01

Если вы попытаетесь обратиться к несуществующему индексу, JavaScript вернёт undefined. Это означает, что элемента с таким индексом в массиве нет. Важно понимать, что отрицательных индексов у массивов в JavaScript не существует в том смысле, в котором они есть, например, в Python. Поэтому запись items[-1] не вернёт последний элемент, а будет воспринята как обращение к свойству объекта с ключом -1. Соответственно, если такого свойства у массива нет (а по умолчанию его нет), результат всегда будет undefined.

// Отрицательный индекс
console.log(items[-1]); // undefined

// Несуществующий индекс
console.log(items[999]); // undefined

Свойство length возвращает количество элементов в массиве.

const array = ['objFirst', 'obj2', 'obj3', 'objLast'];
console.log(array.length); // 4

Это свойство удобно использовать для получения последнего элемента. Индексация начинается с 0, поэтому последний элемент всегда будет иметь индекс на единицу меньше длины массива.

console.log(array[array.length - 1]); // objLast

Массивы в JavaScript можно расширять или уменьшать — их размер не фиксирован. Если вы вручную измените length, то массив подстроится под новое значение.

При увеличении длины в массиве появятся пустые слоты (empty slots) — они существуют формально, но не содержат значений. При обращении к ним вы получите undefined.

const arrayLength = [1, 2, 3];
arrayLength.length = 5;

console.log(arrayLength); // [1, 2, 3, empty × 2]
console.log(arrayLength[4]); // undefined

При уменьшении длины массив обрезается, и все элементы с индексами больше или равными новому значению length будут безвозвратно удалены:

const truncatedArray = [1, 2, 3, 4, 5];
truncatedArray.length = 3;

console.log(truncatedArray); // [1, 2, 3]

Как перебрать массив в JavaScript

Чтобы выполнить действие для каждого элемента массива — например, вывести значения в консоль, обработать данные или изменить элементы, — используют перебор (итерацию). В JavaScript для этого есть несколько способов: классический цикл for, современный for…of и метод forEach(). Рассмотрим каждый на примере следующего массива:

const numbers = ['Один', 'Два', 'Три', 'Четыре', 'Пять'];

Цикл for

Цикл for начинается с индекса первого элемента и далее на каждой итерации увеличивает счётчик i на единицу, пока не достигнет значения length массива. Условие i < numbers.length определяет момент остановки. Этот способ даёт полный контроль: вы можете начать с любого индекса, изменить шаг итерации и даже перебирать массив в обратном порядке.

for (let i = 0; i < numbers.length; i++) {
  console.log(numbers[i]);
}
/*
Один
Два
Три
Четыре
Пять
*/

Цикл for…of

Этот цикл перебирает значения массива напрямую — без счётчика и без необходимости обращаться к элементам по индексу. Для его использования достаточно указать массив, объявить переменную для хранения текущего элемента и использовать ключевое слово of:

for (const item of numbers) {
  console.log(item);
}
/*
Один
Два
Три
Четыре
Пять
*/

Метод forEach()

forEach() — встроенный метод массива, который перебирает элементы по порядку и для каждого вызывает переданную функцию обратного вызова (callback). JavaScript автоматически передаёт в эту функцию три аргумента: текущий элемент, его индекс и ссылку на весь массив.

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

numbers.forEach((item, index) => {
  console.log(`${index}: ${item}`);
});
/*
0: Один
1: Два
2: Три
3: Четыре
4: Пять
*/

Как добавлять и удалять элементы массива

В JavaScript есть четыре основных метода для добавления и удаления элементов массива: unshift() добавляет элемент в начало, push() — в конец, shift() удаляет первый элемент, а pop() — последний. Эти методы изменяют исходный массив и не создают новый.

const elements = ['element01', 'element02'];
console.log(elements); // ['element01', 'element02']

// Добавляем элемент в начало массива
elements.unshift('newElementAtStart');
console.log(elements); // ['newElementAtStart', 'element01', 'element02']

// Добавляем элемент в конец массива
elements.push('newElementAtEnd');
console.log(elements); // ['newElementAtStart', 'element01', 'element02', 'newElementAtEnd']

// Удаляем первый элемент массива
elements.shift();
console.log(elements); // ['element01', 'element02', 'newElementAtEnd']

// Удаляем последний элемент массива
elements.pop();
console.log(elements); // ['element01', 'element02']

Методы shift() и pop() не только удаляют элементы из массива, но и возвращают удалённое значение. Это позволяет сохранить его в переменную и использовать дальше.

const elements2 = ['element01', 'element02', 'element03']; const first = elements2.shift(); console.log(first); // element01 console.log(elements2); // ['element02', 'element03'] const last = elements2.pop(); console.log(last); // element03 console.log(elements2); // ['element02']

Основные методы массивов в JavaScript

Помимо методов добавления и удаления элементов, в JavaScript есть и другие инструменты для работы с массивами. Для удобства разделим их на две группы: методы, которые изменяют исходный массив (мутирующие), и методы, которые возвращают новый массив или значение.

Это далеко не полный перечень, но именно с этими методами мы рекомендуем познакомиться каждому новичку в первую очередь. Они достаточно просты и встречаются во многих задачах.

Методы, которые меняют исходный массив

splice(start, deleteCount, …items) — удаляет указанное количество элементов, начиная с позиции start, и при необходимости вставляет новые элементы на их место. Если вы не укажете deleteCount, то будут удалены все элементы от start и до конца массива.

const modifyArr = [1, 2, 3, 4];
modifyArr.splice(1, 2, 99); // Удаляем два элемента, начиная с индекса 1, и вставляем число 99
console.log(modifyArr); // [1, 99, 4]

sort() — меняет порядок элементов массива. По умолчанию этот метод преобразует элементы в строки и сравнивает их посимвольно. Из-за этого числа могут отсортироваться неправильно. Чтобы этого избежать, нужно передать функцию сравнения: (a, b) => a — b для сортировки по возрастанию или (a, b) => b — a — по убыванию.

const sortNums = [10, 2, 1];
sortNums.sort((a, b) => a - b); // Сортируем элементы по возрастанию
console.log(sortNums); // [1, 2, 10]

reverse() — переворачивает массив, меняя порядок элементов на обратный.

const reverseArr = [1, 2, 3];
reverseArr.reverse();
console.log(reverseArr); // [3, 2, 1]

Методы, которые возвращают новый массив или значение

slice(start, end) — возвращает новый массив, который содержит копию элементов исходного массива от индекса start (включительно) до индекса end (не включая его).

const originalArray = [1, 2, 3, 4];
const part = originalArray.slice(1, 3);
console.log(part); // [2, 3]

concat() — объединяет два или более массива и возвращает новый общий массив.

const firstPart = [1, 2];
const secondPart = [3, 4];
const merged = firstPart.concat(secondPart);
console.log(merged); // [1, 2, 3, 4]

join(separator) — объединяет все элементы массива в одну строку, вставляя между ними указанный разделитель. Если разделитель не указан, по умолчанию метод использует запятую.

const letters = ['a', 'b', 'c'];
const joined = letters.join('-');
console.log(joined); // "a-b-c"

map() — применяет переданную функцию к каждому элементу исходного массива и создаёт новый массив с результатами полученных преобразований.

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

filter() — возвращает новый массив с элементами исходного массива, для которых переданная функция вернула true. Например, можно выбрать только чётные числа.

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

find() — возвращает первый элемент, который соответствует заданному условию, или undefined, если ничего не найдено. Для примера мы можем найти число больше единицы.

const searchSource = [1, 2, 3, 4, 5];
const found = searchSource.find((n) => n > 1);
console.log(found); // 2

includes() — проверяет, содержится ли определённый элемент в выбранном массиве.

const checkSource = [1, 2, 3];
const hasTwo = checkSource.includes(2);
console.log(hasTwo); // true

Что такое вложенные массивы и как с ними работать

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

Начнём с двумерного массива. Его удобно представлять как таблицу из строк и столбцов.

const matrix = [
  [1, 2, 3],
  [4, 5, 6]
];

// Выводим массив табличным видом в консоль
console.table(matrix);
/*
┌─────────┬───┬───┬───┐
│ (index)    │ 0  │ 1  │ 2  │
├─────────┼───┼───┼───┤
│ 0          │ 1  │ 2  │ 3  │
│ 1          │ 4  │ 5  │ 6  │
└─────────┴───┴───┴───┘
*/

Чтобы получить элемент из вложенного массива, необходимо указать два индекса: сначала номер строки (вложенного массива), затем номер столбца (элемента внутри него).

// Обращаемся к элементам двумерного массива
console.log(matrix[0][2]); // 3 (первая строка, третий элемент)
console.log(matrix[1][0]); // 4 (вторая строка, первый элемент)

Массивы в JavaScript могут быть вложены друг в друга на любое количество уровней. Степень вложенности называется глубиной массива. Одномерный массив (например, [1, 2, 3]) имеет глубину «один». Двумерный массив — тот, что мы создали выше, — имеет глубину «два». Трёхмерный массив, соответственно, — глубину «три», и так далее. Однако вы должны помнить: чем больше вложенность, тем сложнее работать с такими структурами. Код становится менее читаемым, а обращение к элементам требует больше индексов и увеличивает риск ошибок.

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

const cube = [
  [[1, 2], [3, 4]],
  [[5, 6], [7, 8]]
];

// Выводим трёхмерный массив в консоль
console.table(cube);
/*
┌─────────┬──────────┬──────────┐
│ (index)    │ 0           │ 1           │
├─────────┼──────────┼──────────┤
│ 0          │ [ 1, 2 ]    │ [ 3, 4 ]    │
│ 1          │ [ 5, 6 ]    │ [ 7, 8 ]    │
└─────────┴──────────┴──────────┘
*/

// Получаем доступ к элементу в трёхмерном массиве
console.log(cube[1][1][1]); // 8
/*
cube[1]       — второй блок [[5, 6], [7, 8]]
cube[1][1]    — вторая строка [7, 8]
cube[1][1][1] — второй элемент «8»
*/

Как проверить равенство массивов в JavaScript

Массив в JavaScript — это объект, а объекты в JavaScript сравниваются по ссылке, а не по содержимому. Операторы == и === проверяют не данные внутри массива, а то, ссылаются ли обе переменные на один и тот же объект в памяти. Поэтому, даже если два массива содержат одинаковые элементы в том же порядке, сравнение вернёт false, если это разные объекты.

const arrayOne = [1, 2];
const arrayTwo = [1, 2];

// Хотя содержимое одинаковое, это разные объекты в памяти
console.log(arrayOne === arrayTwo); // false

Равенство становится возможным только тогда, когда обе переменные указывают на один и тот же массив в памяти. В этом случае нет двух отдельных массивов — есть один объект-массив и две ссылки (переменные), которые указывают на него. Именно поэтому оператор === возвращает true: сравниваются не значения, а адреса в памяти, и они совпадают.

const listA = [1, 2, 3];
const listB = listA; // Две переменные указывают на один и тот же массив в памяти
console.log(listA === listB); // true

Если нужно сравнить содержимое массивов (а не ссылки), в JavaScript для этого нет готового оператора или метода. Поэтому сравнение обычно делают вручную: сначала проверяют длину, затем сравнивают элементы по индексам. Если хотя бы один элемент отличается, массивы считаются разными. Один из простых и читабельных вариантов — через метод every():

const arraysEqual = (a, b) => a.length === b.length && a.every((value, i) => value === b[i]);

const firstList = [1, 2, 3];
const secondList = [1, 2, 3];
const thirdList = [1, 2, 4];

console.log(arraysEqual(firstList, secondList)); // true
console.log(arraysEqual(firstList, thirdList));  // false

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

Типичные ошибки при работе с массивами

В JavaScript существует множество методов для работы с массивами, и при их использовании неизбежно возникают нюансы. Однако мы заметили, что ошибки часто появляются не из-за «сложных» методов, а из-за мелочей: неверной проверки типа, попыток обратиться к несуществующим элементам, ошибок в переборе и прочего. В этом разделе мы собрали самые частые промахи, которые встречаются у новичков, и показываем, как их избежать.

Проверка типа массива с помощью typeof

При работе с массивами вы можете случайно попытаться определить их тип с помощью оператора typeof. Однако в JS массивы реализованы как особый вид объектов, поэтому typeof возвращает object. Этот оператор не различает обычные объекты и массивы.

const checkTypeArray = [];
console.log(typeof checkTypeArray); // "object"

Для проверки используйте метод Array.isArray(), который принимает значение и возвращает true, если это массив, и false — если нет.

console.log(Array.isArray(checkTypeArray)); // true

Обращение к элементам с помощью отрицательных индексов

Некоторые разработчики, знакомые с другими языками вроде Python, предполагают, что отрицательный индекс обращается к элементам с конца массива. В JavaScript это не работает: отрицательное значение воспринимается не как индекс элемента, а как имя свойства объекта. А поскольку такого свойства у массива нет, результатом будет undefined.

const fruitList = ["яблоко", "груша"];
console.log(fruitList[-1]); // undefined

Чтобы получить элемент с конца массива, используйте метод at().

console.log(fruitList.at(-1)); // груша

Прямое изменение свойства length

Свойство length можно изменять напрямую, и иногда его используют для очистки массива, присваивая length = 0. С технической точки зрения это допустимо, но важно понимать: изменение length модифицирует сам массив, а не создаёт новый. Поэтому если этот массив используется в других частях программы, изменение length затронет все эти места.

Чтобы избежать неожиданных побочных эффектов и сохранить исходные данные в безопасности, мы рекомендуем перед изменением массива создать его копию. Например, используйте spread-оператор (), который создаёт поверхностную копию массива:

const numericSeries = [1, 2, 3];
const backupSeries = [...numericSeries]; // Создаём копию перед очисткой
numericSeries.length = 0; // Очищаем массив
console.log(numericSeries); // []
console.log(backupSeries); // [1, 2, 3] (копия осталась)

Неправильное условие завершения цикла

Эта ошибка возникает при переборе массива циклом for, когда в условии используется <= вместо <. В результате цикл выполняет на шаг больше положенного и обращается к элементу с индексом, равным length. А поскольку такого индекса нет, в конце выводится undefined.

const iterationItems = [1, 2, 3];
console.log("Цикл с ошибкой (<=):");
for (let i = 0; i <= iterationItems.length; i++) {
  console.log(iterationItems[i]); // undefined
}

Добавляем строгое сравнение в условии — и всё в порядке.

console.log("Верный цикл (<):");
for (let i = 0; i < iterationItems.length; i++) {
  console.log(iterationItems[i]);
}
/*
1
2
3
*/

Игнорирование мутабельности массивов

Когда вы передаёте массив в функцию, туда попадает не копия, а ссылка на тот же самый объект в памяти. Это значит, что любые изменения массива внутри функции напрямую затрагивают исходный массив. Например, если функция добавляет новый элемент через метод push(), этот элемент появится и в исходном массиве за пределами функции.

const modifyInPlace = (arr) => { arr.push("новый элемент"); }; const sourceList = [1, 2, 3]; modifyInPlace(sourceList); console.log(sourceList); // [1, 2, 3, "новый элемент"]

Если по логике программы вам не нужно изменять исходный массив, безопаснее работать с его копией и возвращать новый результат. Это хорошая практика, поскольку так вы избегаете побочных эффектов, когда один и тот же массив может использоваться в разных местах кода.

const modifyWithCopy = (arr) => {
  const copy = [...arr];
  copy.push("ещё один элемент");
  return copy;
};

const originalList = [1, 2, 3];
const updatedList = modifyWithCopy(originalList);
console.log(originalList); // [1, 2, 3] (оригинал не изменился)
console.log(updatedList);  // [1, 2, 3, "ещё один элемент"]

Задачи для закрепления теории

Закрепим знания и разберём несколько простых задач на работу с массивами. Если вам нужно больше практики, рекомендуем зарегистрироваться на платформе Codewars и решать по одной задаче в день. Регулярная практика поможет вам быстрее освоить синтаксис, научиться применять методы массивов в реальных ситуациях и развить алгоритмическое мышление.

Задача 1. Подсчёт элементов массива

Предположим, у нас есть массив чисел, и нам нужно посчитать количество положительных, отрицательных и нулевых элементов.

const taskNumbers = [-5, 0, 3, -8, 12, 0, -2];

Решение

Создадим переменные-счётчики для каждого типа значений и пройдём по массиву циклом for of.

let positiveCount = 0;
let negativeCount = 0;
let zeroCount = 0;

for (const num of taskNumbers) {
  if (num > 0) {
    positiveCount++;
  } else if (num < 0) {
    negativeCount++;
  } else {
    zeroCount++;
  }
}

console.log({ positiveCount, negativeCount, zeroCount });
// { positiveCount: 2, negativeCount: 3, zeroCount: 2 }

Задача 2. Пересчёт цен со скидкой

У вас есть массив с ценами, которые нельзя менять. Вам нужно получить новый массив со скидкой 15%, но убрать из результата товары, которые после скидки стоят меньше 100.

const productPrices = [
  100, 150, 80, 200, 50, 300, 120, 90, 450, 60,
  1000, 15, 250, 500, 75, 130, 800, 40, 110, 600
];

Решение

Сначала с помощью метода map() мы проходим по исходному массиву и для каждой цены вычисляем новую — получается новый массив значений. Затем применяем filter() к этому массиву и оставляем только те цены, которые после скидки составляют не менее 100.

const discountedPrices = productPrices.map((price) => price * 0.85);
const finalPrices = discountedPrices.filter((price) => price >= 100);

console.log(finalPrices);
// [ 127.5, 170, 255, 102, 382.5, 850, 212.5, 425, 110.5, 680, 510 ]

Задача 3. Очистка и форматирование списка гостей

Предположим, у вас есть массив имён гостей из формы на сайте. В нём есть лишние пробелы и пустые строки. Вам нужно очистить данные, оставить только имена и собрать их в одну строку.

const rawNames = [
 "  Алексей ", "  ", "мария  ", " С ", "  Игорь",
 "ольга", " Пётр ", "Елена ", "   ", "александр",
 "Дмитрий", "светлана", "  И ", "нИкИтА", "  Анна ",
 " Борис", " катЯ ", " ", "владимир", "артём"
];

Решение

Чтобы решить эту задачу, вам необходимо последовательно обработать массив с помощью изученных в этой статье методов, а также некоторых методов строк. Строковые методы в JS вы должны были изучить перед тем, как изучать массивы.

Вот порядок действий:

  • очистите строки от пробелов методом trim() через map();
  • удалите короткие значения через filter(), проверяя свойство length;
  • приведите имена к правильному регистру через map(), используя методы toUpperCase() и toLowerCase();
  • добавьте приставку «Гость» через map();

В завершение объедините всё в строку методом join() и выведите результат.

// Убираем лишние пробелы по краям каждого имени
const trimmedNames = rawNames.map((name) => name.trim());

// Оставляем только те имена, где больше одного символа
const validNames = trimmedNames.filter((name) => name.length > 1);

// Исправляем регистр: первая буква заглавная, остальные строчные 
const capitalizedNames = validNames.map((name) => {
  return name[0].toUpperCase() + name.slice(1).toLowerCase();
});

// Добавляем к каждому имени приставку «Гость»
const guestNames = capitalizedNames.map((name) => `Гость: ${name}`);

// Собираем всё в одну строку с разделителем ", "
const guestListString = guestNames.join(", ");

console.log(guestListString);
// Гость: Алексей, Гость: Мария, Гость: Игорь, Гость: Ольга, Гость: Пётр, Гость: Елена, Гость: Александр, Гость: Дмитрий, Гость: Светлана, Гость: Никита, Гость: Анна, Гость: Борис, Гость: Катя, Гость: Владимир, Гость: Артём

Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!




Курс с трудоустройством: «Профессия Фронтенд-разработчик + ИИ» Узнать о курсе
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована