Привет! Если ты когда-нибудь писал на JavaScript, то наверняка сталкивался с массивами и объектами. Это основа, на которой держится почти любой код. Но как с ними работать грамотно? Как не плодить лишние переменные и не терять данные? Сегодня разберемся на живых примерах, без скучной теории.

Что такое массив и объект? Коротко для тех, кто забыл

Массив — это список элементов. Представь коробку с пронумерованными ячейками. Нумерация начинается с нуля. В каждой ячейке может быть что угодно: число, строка, другой массив или объект.

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

Обе структуры можно менять: добавлять, удалять, изменять элементы. И JavaScript даёт для этого кучу удобных методов.

Основные операции с массивами: добавление, удаление, поиск

Начнём с простого. Допустим, у нас есть массив чисел:

let numbers = [10, 20, 30, 40];

Хотим добавить в конец — используем push:

numbers.push(50); // теперь [10, 20, 30, 40, 50]

Удалить с конца — pop:

let last = numbers.pop(); // last = 50, numbers = [10, 20, 30, 40]

Добавить в начало — unshift:

numbers.unshift(5); // [5, 10, 20, 30, 40]

Удалить из начала — shift:

let first = numbers.shift(); // first = 5, numbers = [10, 20, 30, 40]

Найти индекс элемента — indexOf:

let pos = numbers.indexOf(20); // 1

Проверить, есть ли элемент — includes:

let hasThirty = numbers.includes(30); // true

Удалить элемент по индексу — splice:

numbers.splice(1, 1); // удаляем один элемент с индекса 1, остаётся [10, 30, 40]

Вот так просто. Но это только разминка.

Лайфхак: Если нужно удалить элемент по значению, а не по индексу, сначала найди индекс через indexOf, а потом удали через splice. Или используй filter (о нём ниже).

Обход массивов: forEach, map, filter, reduce

Это мощные методы, которые заменяют циклы. Они делают код чище и понятнее.

forEach — просто пробегается по каждому элементу и выполняет действие. Ничего не возвращает.

numbers.forEach(function(num) {
  console.log(num * 2);
});

map — создаёт новый массив, преобразуя каждый элемент.

let doubled = numbers.map(function(num) {
  return num * 2;
}); // doubled = [20, 60, 80]

filter — отбирает элементы, которые подходят под условие.

let bigNumbers = numbers.filter(function(num) {
  return num > 20;
}); // bigNumbers = [30, 40]

reduce — сворачивает массив в одно значение (сумму, произведение, строку).

let sum = numbers.reduce(function(acc, num) {
  return acc + num;
}, 0); // sum = 80

Эти методы можно комбинировать. Например, отфильтровать, потом удвоить, потом сложить.

МетодЧто делаетВозвращает
forEachВыполняет функцию для каждого элементаundefined
mapПреобразует каждый элементНовый массив той же длины
filterОтбирает элементы по условиюНовый массив (может быть короче)
reduceСобирает одно значение из всех элементовЛюбой тип

Работа с объектами: добавление, удаление, перебор свойств

Объекты в JavaScript — это как ассоциативные массивы. Свойства можно добавлять на лету.

let user = {
  name: 'Иван',
  age: 30
};

// Добавляем новое свойство
user.city = 'Москва';

// Изменяем существующее
user.age = 31;

// Удаляем свойство
delete user.city;

Перебрать все свойства объекта можно с помощью for...in:

for (let key in user) {
  console.log(key + ': ' + user[key]);
}

Но есть и современные методы: Object.keys, Object.values, Object.entries. Они возвращают массивы.

let keys = Object.keys(user); // ['name', 'age']
let values = Object.values(user); // ['Иван', 31]
let entries = Object.entries(user); // [['name', 'Иван'], ['age', 31]]

Это очень удобно, когда нужно, например, вывести все данные в таблицу или отфильтровать свойства.

Сортировка и копирование: как не сломать оригинал

Сортировка массива — метод sort. По умолчанию он сортирует как строки (даже числа). Поэтому для чисел нужно передать функцию сравнения.

let nums = [40, 10, 100, 30];
nums.sort(function(a, b) {
  return a - b;
}); // [10, 30, 40, 100]

Важно: sort меняет исходный массив. Если нужно сохранить оригинал, сначала сделай копию.

Копирование массива — используй slice или spread-оператор (...):

let copy1 = nums.slice();
let copy2 = [...nums];

Для объектов — Object.assign или spread:

let userCopy = Object.assign({}, user);
let userCopy2 = { ...user };

Но помни: это поверхностное копирование. Если внутри есть вложенные объекты или массивы, они будут скопированы по ссылке. Для глубокого копирования используй JSON.parse(JSON.stringify(obj)) или библиотеки.

Правило: Если мутируешь (изменяешь) массив или объект, который передаётся в другую функцию, делай копию. Иначе рискуешь получить неожиданные баги.

Практический пример: фильтрация и группировка данных

Представь, что у нас есть список пользователей:

let users = [
  { name: 'Анна', age: 25, city: 'Москва' },
  { name: 'Петр', age: 30, city: 'СПб' },
  { name: 'Мария', age: 22, city: 'Москва' },
  { name: 'Иван', age: 35, city: 'СПб' }
];

Хотим получить только москвичей старше 23 лет:

let filtered = users.filter(function(user) {
  return user.city === 'Москва' && user.age > 23;
});
// [{ name: 'Анна', age: 25, city: 'Москва' }]

А теперь сгруппируем по городам:

let grouped = users.reduce(function(acc, user) {
  if (!acc[user.city]) {
    acc[user.city] = [];
  }
  acc[user.city].push(user);
  return acc;
}, {});
// { Москва: [Анна, Мария], СПб: [Петр, Иван] }

Красиво, правда? Без циклов, без лишних переменных.

Что в итоге

Манипуляция массивами и объектами — это база, которую нужно знать наизусть. Мы разобрали основные методы: добавление, удаление, поиск, обход, сортировку, копирование. Научились комбинировать map, filter, reduce для решения реальных задач. Главное — не бояться экспериментировать и всегда помнить про мутации. Если будешь следовать этим простым правилам, код станет чище, а баги — реже.

Студия WNDER