⚡ JavaScript

जावास्क्रिप्ट (Node.js) में स्ट्रिंग्स और टेक्स्ट के साथ काम: विस्तृत गाइड

Массив — это список. Один из самых используемых инструментов в программировании. Список пользователей, список товаров, список задач — всё это массивы. В этом уроке вы не только узнаете, как создавать массивы и работать с ними, но и освоите мощнейшие методы map, filter и reduce, которые делают код элегантным и лаконичным.

Что такое массив? Аналогия со списком

Представьте список покупок в блокноте: молоко, хлеб, яблоки, сыр, макароны. Каждый элемент находится на определённой строчке (первый, второй, третий...). Вы можете добавить новый пункт в конец, вычеркнуть что-то, проверить что уже куплено.

Массив в JavaScript — это exactly такой список, только в памяти компьютера. Формально: массив — это упорядоченная коллекция элементов, доступных по числовому индексу.

Зачем нужны массивы? Без них пришлось бы создавать отдельную переменную для каждого элемента:

// БЕЗ массива — ужасно:
let товар1 = "молоко";
let товар2 = "хлеб";
let товар3 = "яблоки";
// А если товаров 100? А если мы не знаем заранее сколько их?

// С массивом — отлично:
let покупки = ["молоко", "хлеб", "яблоки", "сыр", "макароны"];

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

// Литеральная запись (рекомендуется):
let пустойМассив = [];
let числа = [1, 2, 3, 4, 5];
let имена = ["Аня", "Боря", "Вася"];
let смешанный = [1, "два", true, null]; // Можно мешать типы (но не рекомендуется)

// Через конструктор (редко используется):
let тоже = new Array(1, 2, 3);

// Массив массивов (двумерный):
let матрица = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];
console.log(матрица[1][2]); // 6 (вторая строка, третий элемент)

Индексы: почему с нуля?

Каждый элемент массива имеет номер — индекс. И здесь всех новичков ждёт сюрприз: индексы начинаются с 0, а не с 1!

Почему? Это идёт из математики и низкоуровневого программирования. Индекс показывает "смещение от начала". Первый элемент находится на нулевом смещении от начала массива. Технически это оптимальнее. Сейчас это просто исторически сложившееся соглашение.

let фрукты = ["яблоко", "банан", "апельсин", "груша"];
//  Индексы:    0          1        2            3

console.log(фрукты[0]); // "яблоко" (первый)
console.log(фрукты[1]); // "банан" (второй)
console.log(фрукты[2]); // "апельсин" (третий)
console.log(фрукты[3]); // "груша" (четвёртый)
console.log(фрукты[4]); // undefined (такого элемента нет)

// Последний элемент:
let последний = фрукты[фрукты.length - 1]; // "груша"
// фрукты.length = 4, значит последний индекс = 4 - 1 = 3

// Изменение элемента:
фрукты[1] = "манго";
console.log(фрукты); // ["яблоко", "манго", "апельсин", "груша"]

Свойство length

let числа = [10, 20, 30, 40, 50];
console.log(числа.length); // 5 (количество элементов)

// Длина меняется при добавлении/удалении:
числа.push(60);
console.log(числа.length); // 6

// Можно принудительно обрезать массив:
числа.length = 3;
console.log(числа); // [10, 20, 30] — остальные удалены!

Основные методы: добавление и удаление

let стек = ["а", "б", "в"];

// push — добавить В КОНЕЦ (один или несколько):
стек.push("г");
console.log(стек); // ["а", "б", "в", "г"]
стек.push("д", "е");
console.log(стек); // ["а", "б", "в", "г", "д", "е"]

// pop — удалить последний элемент И ВЕРНУТЬ его:
let последний = стек.pop();
console.log(последний); // "е"
console.log(стек);      // ["а", "б", "в", "г", "д"]

// unshift — добавить В НАЧАЛО:
стек.unshift("0");
console.log(стек); // ["0", "а", "б", "в", "г", "д"]

// shift — удалить первый элемент И ВЕРНУТЬ его:
let первый = стек.shift();
console.log(первый); // "0"
console.log(стек);   // ["а", "б", "в", "г", "д"]

splice — универсальный метод редактирования

let цвета = ["красный", "зелёный", "синий", "жёлтый", "белый"];

// splice(индекс, количество_удалить, ...добавить):

// Удалить 2 элемента начиная с индекса 1:
let удалённые = цвета.splice(1, 2);
console.log(удалённые); // ["зелёный", "синий"]
console.log(цвета);     // ["красный", "жёлтый", "белый"]

// Добавить элемент на позицию 1 (не удаляя ничего):
цвета.splice(1, 0, "фиолетовый");
console.log(цвета); // ["красный", "фиолетовый", "жёлтый", "белый"]

// Заменить элемент:
цвета.splice(2, 1, "оранжевый");
console.log(цвета); // ["красный", "фиолетовый", "оранжевый", "белый"]

Методы поиска

let числа = [3, 7, 1, 9, 2, 7, 4];

// indexOf — найти первый индекс элемента (-1 если нет):
console.log(числа.indexOf(7));  // 1 (первое вхождение)
console.log(числа.indexOf(99)); // -1 (не найдено)

// lastIndexOf — найти последний индекс:
console.log(числа.lastIndexOf(7)); // 5 (последнее вхождение)

// includes — проверить, есть ли элемент:
console.log(числа.includes(9));  // true
console.log(числа.includes(99)); // false

// find — найти первый элемент, подходящий по условию:
let первоеБольшое = числа.find(n => n > 5);
console.log(первоеБольшое); // 7

// findIndex — найти индекс первого подходящего:
let индекс = числа.findIndex(n => n > 5);
console.log(индекс); // 1

Метод forEach: перебор элементов

forEach — это как сказать: "для каждого элемента в списке — сделай вот это". Замена цикла for для работы с массивами.

let имена = ["Аня", "Боря", "Вася", "Галя"];

// Традиционный цикл for:
for (let i = 0; i < имена.length; i++) {
  console.log(`Привет, ${имена[i]}!`);
}

// forEach — элегантнее:
имена.forEach(function(имя) {
  console.log(`Привет, ${имя}!`);
});

// Со стрелочной функцией ещё короче:
имена.forEach(имя => console.log(`Привет, ${имя}!`));

// forEach также даёт индекс и сам массив:
имена.forEach((имя, индекс) => {
  console.log(`${индекс + 1}. ${имя}`);
});
// 1. Аня
// 2. Боря
// 3. Вася
// 4. Галя

Важно: forEach ничего не возвращает (return undefined). Он нужен только для "побочных эффектов" — вывода, изменения внешних переменных, и т.д.

Метод map: трансформация массива

map — один из самых полезных методов. Он создаёт НОВЫЙ массив, применяя функцию к каждому элементу. Аналогия: как конвейер на фабрике — каждый элемент проходит через "преобразователь" и получается новый элемент.

let числа = [1, 2, 3, 4, 5];

// Создать новый массив, удвоив каждый элемент:
let удвоенные = числа.map(n => n * 2);
console.log(удвоенные); // [2, 4, 6, 8, 10]
console.log(числа);     // [1, 2, 3, 4, 5] — исходный не изменился!

// Квадрат каждого числа:
let квадраты = числа.map(n => n ** 2);
console.log(квадраты); // [1, 4, 9, 16, 25]

// Массив объектов → массив строк:
let пользователи = [
  { имя: "Аня", возраст: 20 },
  { имя: "Боря", возраст: 25 },
  { имя: "Вася", возраст: 18 }
];

let имена = пользователи.map(п => п.имя);
console.log(имена); // ["Аня", "Боря", "Вася"]

let карточки = пользователи.map(п => `${п.имя} (${п.возраст} лет)`);
console.log(карточки); // ["Аня (20 лет)", "Боря (25 лет)", "Вася (18 лет)"]

Метод filter: фильтрация массива

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

let числа = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Только чётные числа:
let чётные = числа.filter(n => n % 2 === 0);
console.log(чётные); // [2, 4, 6, 8, 10]

// Только числа больше 5:
let большие = числа.filter(n => n > 5);
console.log(большие); // [6, 7, 8, 9, 10]

// Реальный пример: фильтр товаров:
let товары = [
  { название: "Ноутбук", цена: 50000, наличие: true },
  { название: "Мышь", цена: 1500, наличие: false },
  { название: "Клавиатура", цена: 3000, наличие: true },
  { название: "Монитор", цена: 25000, наличие: true },
  { название: "Наушники", цена: 5000, наличие: false }
];

// Только товары в наличии:
let вНаличии = товары.filter(т => т.наличие);
console.log(вНаличии.map(т => т.название)); // ["Ноутбук", "Клавиатура", "Монитор"]

// Товары дешевле 10000 в наличии:
let доступные = товары.filter(т => т.наличие && т.цена < 10000);
console.log(доступные.map(т => т.название)); // ["Клавиатура"]

Метод reduce: свёртка массива

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

// Синтаксис: массив.reduce((аккумулятор, текущий) => ..., начальноеЗначение)

let числа = [1, 2, 3, 4, 5];

// Сумма всех чисел:
let сумма = числа.reduce((накоп, текущий) => накоп + текущий, 0);
console.log(сумма); // 15
// Как это работает:
// Шаг 1: накоп=0,  текущий=1 → 0+1=1
// Шаг 2: накоп=1,  текущий=2 → 1+2=3
// Шаг 3: накоп=3,  текущий=3 → 3+3=6
// Шаг 4: накоп=6,  текущий=4 → 6+4=10
// Шаг 5: накоп=10, текущий=5 → 10+5=15

// Максимальное число:
let максимум = числа.reduce((макс, текущий) => текущий > макс ? текущий : макс, -Infinity);
console.log(максимум); // 5

// Реальный пример: сумма заказа:
let корзина = [
  { товар: "Кофе", цена: 350, количество: 2 },
  { товар: "Круассан", цена: 120, количество: 3 },
  { товар: "Сок", цена: 180, количество: 1 }
];

let итого = корзина.reduce((сумма, позиция) => {
  return сумма + позиция.цена * позиция.количество;
}, 0);
console.log(`Итого к оплате: ${итого} руб.`); // Итого к оплате: 1420 руб.

Цепочки методов

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

let студенты = [
  { имя: "Аня", оценка: 85, группа: "А" },
  { имя: "Боря", оценка: 60, группа: "Б" },
  { имя: "Вася", оценка: 92, группа: "А" },
  { имя: "Галя", оценка: 75, группа: "А" },
  { имя: "Дима", оценка: 55, группа: "Б" }
];

// Найти среднюю оценку студентов группы "А":
let средняяА = студенты
  .filter(с => с.группа === "А")      // оставить только группу А
  .map(с => с.оценка)                 // взять только оценки
  .reduce((сумма, оц) => сумма + оц, 0) / студенты.filter(с => с.группа === "А").length;

console.log(`Средняя оценка группы А: ${средняяА}`); // 84

Spread оператор (...)

Spread оператор (...) "разворачивает" массив — как высыпать содержимое коробки на стол.

let массив1 = [1, 2, 3];
let массив2 = [4, 5, 6];

// Объединить массивы:
let объединённый = [...массив1, ...массив2];
console.log(объединённый); // [1, 2, 3, 4, 5, 6]

// Добавить элементы в середину:
let с99 = [...массив1, 99, ...массив2];
console.log(с99); // [1, 2, 3, 99, 4, 5, 6]

// Скопировать массив (не ссылку!):
let копия = [...массив1];
копия.push(100);
console.log(массив1); // [1, 2, 3] — оригинал не изменился
console.log(копия);   // [1, 2, 3, 100]

// Передать элементы массива как аргументы функции:
let числа = [3, 1, 4, 1, 5, 9, 2, 6];
let макс = Math.max(...числа); // То же что Math.max(3, 1, 4, 1, 5, 9, 2, 6)
console.log(макс); // 9

Другие полезные методы

let числа = [3, 1, 4, 1, 5, 9, 2, 6];

// sort — сортировка (ВАЖНО: по умолчанию как строки!):
let строковаяСорт = [10, 9, 2, 1, 21].sort();
console.log(строковаяСорт); // [1, 10, 2, 21, 9] — неправильно!

// Правильная числовая сортировка:
let правильная = [10, 9, 2, 1, 21].sort((а, б) => а - б);
console.log(правильная); // [1, 2, 9, 10, 21] — правильно!

// reverse — перевернуть:
console.log([1, 2, 3].reverse()); // [3, 2, 1]

// join — объединить в строку:
console.log(["Привет", "мир"].join(" ")); // "Привет мир"
console.log([1, 2, 3].join("-"));         // "1-2-3"

// slice — вырезать подмассив (не меняет оригинал):
let буквы = ["а", "б", "в", "г", "д"];
console.log(буквы.slice(1, 3)); // ["б", "в"] (с 1 до 3, не включая 3)
console.log(буквы.slice(-2));   // ["г", "д"] (последние 2)

// flat — распрямить вложенные массивы:
let вложенный = [1, [2, 3], [4, [5, 6]]];
console.log(вложенный.flat());    // [1, 2, 3, 4, [5, 6]] (1 уровень)
console.log(вложенный.flat(2));   // [1, 2, 3, 4, 5, 6] (2 уровня)

// every — все ли элементы удовлетворяют условию?
console.log([2, 4, 6].every(n => n % 2 === 0)); // true (все чётные)
console.log([2, 3, 6].every(n => n % 2 === 0)); // false (3 нечётное)

// some — хотя бы один удовлетворяет условию?
console.log([1, 3, 5].some(n => n > 4)); // true (5 > 4)

Практический пример: система оценок

const оценки = [85, 92, 78, 65, 90, 55, 88, 72, 95, 60];

// Статистика:
const количество = оценки.length;
const сумма = оценки.reduce((с, о) => с + о, 0);
const среднее = (сумма / количество).toFixed(1);
const максимум = Math.max(...оценки);
const минимум = Math.min(...оценки);

// Категории:
const отличников = оценки.filter(о => о >= 90).length;
const провалили = оценки.filter(о => о < 60).length;

console.log(`📊 Статистика класса:`);
console.log(`   Студентов: ${количество}`);
console.log(`   Средняя оценка: ${среднее}`);
console.log(`   Лучшая: ${максимум}, Худшая: ${минимум}`);
console.log(`   Отличников: ${отличников}`);
console.log(`   Не сдали: ${провалили}`);

Типичные ошибки новичков

  • Индекс начинается с 1. Нет! С 0. Первый элемент: массив[0], последний: массив[массив.length - 1].
  • Мутация при копировании. let б = а не копирует массив — оба указывают на один и тот же массив! Для копии используйте let б = [...а] или а.slice().
  • Сортировка чисел по умолчанию. [10, 9, 2].sort() даст [10, 2, 9] (сортировка как строки). Всегда передавайте компаратор: .sort((а, б) => а - б).
  • forEach не возвращает новый массив. Если нужен новый массив — используйте map, не forEach.
  • map/filter не меняют оригинал. Они создают НОВЫЙ массив. Если не сохранить в переменную — результат потеряется.

Итого

В этом уроке мы узнали:

  1. Массив — упорядоченный список элементов, доступных по числовому индексу (с 0).
  2. push/pop — добавить/удалить с конца. unshift/shift — добавить/удалить с начала.
  3. splice — универсальный метод добавления/удаления/замены в любом месте.
  4. forEach — перебрать каждый элемент (ничего не возвращает).
  5. map — создать новый массив, трансформируя каждый элемент.
  6. filter — создать новый массив из элементов, прошедших условие.
  7. reduce — свернуть массив в одно значение, накапливая результат.
  8. Spread (...) — развернуть массив: копирование, объединение, передача как аргументов.

В следующем уроке мы изучим объекты и классы — способ группировать связанные данные и действия.