← JavaScript/Методы массивов#58 из 383← ПредыдущийСледующий →+30 XP
Полезно по теме:Гайд: как учить JavaScriptПрактика: JS базаПрактика: async и сетьТермин: Closure

Продвинутые методы массивов

В дашборде аналитики Shopify нужно: отфильтровать заказы за месяц, посчитать общую выручку, найти топ-3 товара по продажам. Всё это — методы массивов в цепочке.

На основе предыдущих уроков

Мы уже знаем map, filter, find из урока 08. Теперь разберём более мощные инструменты, которые используются в аналитике и сложной обработке данных.

Какую проблему решают эти методы?

В реальных проектах данные нужно не просто перебирать, но и агрегировать (суммировать, группировать), проверять наличие условий, сортировать. Методы массивов делают это декларативно — описываешь ЧТО хочешь, а не КАК это сделать.

reduce — свёртка массива в одно значение

Самый мощный и гибкий метод. Превращает массив в что угодно: число, строку, объект.

const prices = [100, 250, 80, 420]

// Сумма
const total = prices.reduce((accumulator, current) => accumulator + current, 0)
// 0 → 100 → 350 → 430 → 850
console.log(total)  // 850

// accumulator (acc) — накопитель, начинается с начального значения (0)
// current — текущий элемент массива

Reduce может создавать объекты и группировать данные:

const orders = [
  { status: 'done', amount: 100 },
  { status: 'pending', amount: 200 },
  { status: 'done', amount: 150 },
]

const byStatus = orders.reduce((acc, order) => {
  acc[order.status] = (acc[order.status] || 0) + order.amount
  return acc
}, {})
// { done: 250, pending: 200 }

some и every — проверка условий

const cartItems = [
  { name: 'Молоко', inStock: true },
  { name: 'Хлеб',  inStock: true },
  { name: 'Масло', inStock: false },
]

// some — хотя бы один элемент удовлетворяет условию?
const hasOutOfStock = cartItems.some(item => !item.inStock)
console.log(hasOutOfStock)  // true (масло недоступно)

// every — все элементы удовлетворяют условию?
const allAvailable = cartItems.every(item => item.inStock)
console.log(allAvailable)   // false

sort — сортировка

Важно: sort изменяет исходный массив! И по умолчанию сортирует как строки.

const nums = [10, 2, 30, 1]
nums.sort()              // [1, 10, 2, 30] — строковая сортировка! Неверно
nums.sort((a, b) => a - b)  // [1, 2, 10, 30] — числовая по возрастанию
nums.sort((a, b) => b - a)  // [30, 10, 2, 1] — по убыванию

// Сортировка объектов
products.sort((a, b) => a.price - b.price)    // по цене
products.sort((a, b) => b.rating - a.rating)  // по рейтингу (убывание)

Чейнинг — цепочки методов

Методы можно вызывать последовательно — каждый следующий работает с результатом предыдущего:

const result = products
  .filter(p => p.inStock)         // оставляем доступные
  .sort((a, b) => a.price - b.price)  // сортируем по цене
  .slice(0, 5)                    // берём первые 5
  .map(p => p.name)               // берём только названия

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

Ошибка 1: Забыть начальное значение в reduce

const nums = [1, 2, 3]
nums.reduce((acc, n) => acc + n)    // 6 — работает, но опасно
nums.reduce((acc, n) => acc + n, 0) // 6 — правильно, явное начало
// Для пустого массива без начального значения будет ошибка!
[].reduce((acc, n) => acc + n)      // TypeError!
[].reduce((acc, n) => acc + n, 0)   // 0 — безопасно

Ошибка 2: Мутировать массив при sort без копирования

const products = [{ price: 100 }, { price: 50 }]
products.sort((a, b) => a.price - b.price)  // меняет исходный массив!

// Безопасно:
const sorted = [...products].sort((a, b) => a.price - b.price)

Ошибка 3: Сортировать числа без функции сравнения

[10, 9, 100].sort()           // [10, 100, 9] — строковая сортировка!
[10, 9, 100].sort((a, b) => a - b)  // [9, 10, 100] — правильно

В реальных проектах

Цепочки методов массивов — это основа работы с данными на фронтенде. Redux selectors, Vue computed properties, фильтры каталога, аналитические дашборды — везде используется комбинация filter + map + reduce.

Примеры

Аналитика продаж для дашборда

const sales = [
  { product: 'Ноутбук',  amount: 75000, month: 'Jan', category: 'tech'      },
  { product: 'Мышь',     amount: 1500,  month: 'Jan', category: 'tech'      },
  { product: 'Стол',     amount: 12000, month: 'Feb', category: 'furniture' },
  { product: 'Монитор',  amount: 25000, month: 'Feb', category: 'tech'      },
  { product: 'Кресло',   amount: 18000, month: 'Jan', category: 'furniture' },
  { product: 'Наушники', amount: 8000,  month: 'Feb', category: 'tech'      },
]

// Общая выручка от tech в январе
const techJanRevenue = sales
  .filter(s => s.category === 'tech' && s.month === 'Jan')
  .reduce((sum, s) => sum + s.amount, 0)
console.log('Tech/Jan:', techJanRevenue)  // 76500

// Топ-3 продажи по убыванию суммы
const top3 = [...sales]
  .sort((a, b) => b.amount - a.amount)
  .slice(0, 3)
  .map(s => s.product)
console.log('Топ-3:', top3)  // ['Ноутбук', 'Монитор', 'Кресло']

// Группировка выручки по категориям
const revenueByCategory = sales.reduce((acc, s) => {
  acc[s.category] = (acc[s.category] || 0) + s.amount
  return acc
}, {})
console.log(revenueByCategory)
// { tech: 109500, furniture: 30000 }

// Есть ли продажи дороже 50000?
const hasHighValue = sales.some(s => s.amount > 50000)
console.log('Есть крупные продажи:', hasHighValue)  // true

Продвинутые методы массивов

В дашборде аналитики Shopify нужно: отфильтровать заказы за месяц, посчитать общую выручку, найти топ-3 товара по продажам. Всё это — методы массивов в цепочке.

На основе предыдущих уроков

Мы уже знаем map, filter, find из урока 08. Теперь разберём более мощные инструменты, которые используются в аналитике и сложной обработке данных.

Какую проблему решают эти методы?

В реальных проектах данные нужно не просто перебирать, но и агрегировать (суммировать, группировать), проверять наличие условий, сортировать. Методы массивов делают это декларативно — описываешь ЧТО хочешь, а не КАК это сделать.

reduce — свёртка массива в одно значение

Самый мощный и гибкий метод. Превращает массив в что угодно: число, строку, объект.

const prices = [100, 250, 80, 420]

// Сумма
const total = prices.reduce((accumulator, current) => accumulator + current, 0)
// 0 → 100 → 350 → 430 → 850
console.log(total)  // 850

// accumulator (acc) — накопитель, начинается с начального значения (0)
// current — текущий элемент массива

Reduce может создавать объекты и группировать данные:

const orders = [
  { status: 'done', amount: 100 },
  { status: 'pending', amount: 200 },
  { status: 'done', amount: 150 },
]

const byStatus = orders.reduce((acc, order) => {
  acc[order.status] = (acc[order.status] || 0) + order.amount
  return acc
}, {})
// { done: 250, pending: 200 }

some и every — проверка условий

const cartItems = [
  { name: 'Молоко', inStock: true },
  { name: 'Хлеб',  inStock: true },
  { name: 'Масло', inStock: false },
]

// some — хотя бы один элемент удовлетворяет условию?
const hasOutOfStock = cartItems.some(item => !item.inStock)
console.log(hasOutOfStock)  // true (масло недоступно)

// every — все элементы удовлетворяют условию?
const allAvailable = cartItems.every(item => item.inStock)
console.log(allAvailable)   // false

sort — сортировка

Важно: sort изменяет исходный массив! И по умолчанию сортирует как строки.

const nums = [10, 2, 30, 1]
nums.sort()              // [1, 10, 2, 30] — строковая сортировка! Неверно
nums.sort((a, b) => a - b)  // [1, 2, 10, 30] — числовая по возрастанию
nums.sort((a, b) => b - a)  // [30, 10, 2, 1] — по убыванию

// Сортировка объектов
products.sort((a, b) => a.price - b.price)    // по цене
products.sort((a, b) => b.rating - a.rating)  // по рейтингу (убывание)

Чейнинг — цепочки методов

Методы можно вызывать последовательно — каждый следующий работает с результатом предыдущего:

const result = products
  .filter(p => p.inStock)         // оставляем доступные
  .sort((a, b) => a.price - b.price)  // сортируем по цене
  .slice(0, 5)                    // берём первые 5
  .map(p => p.name)               // берём только названия

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

Ошибка 1: Забыть начальное значение в reduce

const nums = [1, 2, 3]
nums.reduce((acc, n) => acc + n)    // 6 — работает, но опасно
nums.reduce((acc, n) => acc + n, 0) // 6 — правильно, явное начало
// Для пустого массива без начального значения будет ошибка!
[].reduce((acc, n) => acc + n)      // TypeError!
[].reduce((acc, n) => acc + n, 0)   // 0 — безопасно

Ошибка 2: Мутировать массив при sort без копирования

const products = [{ price: 100 }, { price: 50 }]
products.sort((a, b) => a.price - b.price)  // меняет исходный массив!

// Безопасно:
const sorted = [...products].sort((a, b) => a.price - b.price)

Ошибка 3: Сортировать числа без функции сравнения

[10, 9, 100].sort()           // [10, 100, 9] — строковая сортировка!
[10, 9, 100].sort((a, b) => a - b)  // [9, 10, 100] — правильно

В реальных проектах

Цепочки методов массивов — это основа работы с данными на фронтенде. Redux selectors, Vue computed properties, фильтры каталога, аналитические дашборды — везде используется комбинация filter + map + reduce.

Примеры

Аналитика продаж для дашборда

const sales = [
  { product: 'Ноутбук',  amount: 75000, month: 'Jan', category: 'tech'      },
  { product: 'Мышь',     amount: 1500,  month: 'Jan', category: 'tech'      },
  { product: 'Стол',     amount: 12000, month: 'Feb', category: 'furniture' },
  { product: 'Монитор',  amount: 25000, month: 'Feb', category: 'tech'      },
  { product: 'Кресло',   amount: 18000, month: 'Jan', category: 'furniture' },
  { product: 'Наушники', amount: 8000,  month: 'Feb', category: 'tech'      },
]

// Общая выручка от tech в январе
const techJanRevenue = sales
  .filter(s => s.category === 'tech' && s.month === 'Jan')
  .reduce((sum, s) => sum + s.amount, 0)
console.log('Tech/Jan:', techJanRevenue)  // 76500

// Топ-3 продажи по убыванию суммы
const top3 = [...sales]
  .sort((a, b) => b.amount - a.amount)
  .slice(0, 3)
  .map(s => s.product)
console.log('Топ-3:', top3)  // ['Ноутбук', 'Монитор', 'Кресло']

// Группировка выручки по категориям
const revenueByCategory = sales.reduce((acc, s) => {
  acc[s.category] = (acc[s.category] || 0) + s.amount
  return acc
}, {})
console.log(revenueByCategory)
// { tech: 109500, furniture: 30000 }

// Есть ли продажи дороже 50000?
const hasHighValue = sales.some(s => s.amount > 50000)
console.log('Есть крупные продажи:', hasHighValue)  // true

Задание

Ты разрабатываешь аналитику для магазина. Используй методы массивов: найди среднюю цену товаров в наличии (inStock: true). Цепочка: filter → map → reduce, потом раздели на количество.

Подсказка

filter(p => p.inStock), затем map(p => p.price), затем reduce((sum, price) => sum + price, 0)

Загружаем среду выполнения...
Загружаем AI-помощника...