Tablice JavaScript mają jedno z najbogatszych API metod spośród popularnych języków programowania. Jednak większość poradników uczy map i filter na wymyślonych przykładach — podwajanie liczb w tablicy, filtrowanie liczb parzystych — a potem zostawia Cię samemu z resztą. Przejdźmy przez metody, które naprawdę pojawiają się w kodzie produkcyjnym, używając realistycznych danych: produktów, zamówień i rekordów użytkowników.

Zestaw danych, z którego będziemy korzystać

Aby przykłady były osadzone w rzeczywistości, przez cały artykuł będziemy używać realistycznego katalogu produktów:

js
const products = [
  { id: 1, name: 'Wireless Keyboard',  category: 'electronics', price: 79.99,  rating: 4.5, inStock: true  },
  { id: 2, name: 'Mechanical Keyboard', category: 'electronics', price: 149.99, rating: 4.8, inStock: true  },
  { id: 3, name: 'USB-C Hub',          category: 'electronics', price: 49.99,  rating: 4.2, inStock: false },
  { id: 4, name: 'Standing Desk',       category: 'furniture',   price: 499.99, rating: 4.6, inStock: true  },
  { id: 5, name: 'Desk Lamp',           category: 'furniture',   price: 39.99,  rating: 4.1, inStock: true  },
  { id: 6, name: 'Monitor Arm',         category: 'electronics', price: 89.99,  rating: 4.7, inStock: false },
];

map() — przekształcanie każdego elementu

Array.prototype.map() tworzy nową tablicę, stosując funkcję do każdego elementu. To koń roboczy transformacji danych — przekształca odpowiedzi API w format potrzebny interfejsowi użytkownika:

js
// Extract just the display data for a product list component
const productCards = products.map(product => ({
  id:       product.id,
  name:     product.name,
  price:    `$${product.price.toFixed(2)}`,
  badge:    product.inStock ? 'In Stock' : 'Out of Stock',
  stars:    '★'.repeat(Math.round(product.rating))
}));

// productCards[0] → { id: 1, name: 'Wireless Keyboard', price: '$79.99', badge: 'In Stock', stars: '★★★★★' }

// Apply a discount to all prices
const discounted = products.map(p => ({
  ...p,
  price:       parseFloat((p.price * 0.9).toFixed(2)),
  originalPrice: p.price
}));

map() nigdy nie mutuje oryginalnej tablicy — zawsze zwraca nową. Dlatego jest bezpieczne do łańcuchowania i warto preferować je nad pętlą for, gdy celem jest transformacja.

filter() — pobieranie podzbioru

filter() zwraca nową tablicę zawierającą tylko te elementy, dla których callback zwraca true:

js
const inStockProducts  = products.filter(p => p.inStock);
const electronicsOnly  = products.filter(p => p.category === 'electronics');
const affordableInStock = products.filter(p => p.inStock && p.price < 100);

// Chain map + filter to get display-ready affordable in-stock electronics
const featuredItems = products
  .filter(p => p.inStock && p.rating >= 4.5)
  .map(p => ({ id: p.id, name: p.name, price: `$${p.price}` }));

reduce() — scyzoryk szwajcarski

Array.prototype.reduce() to metoda, której programiści unikają, bo sygnatura wygląda groźnie. Ale gdy już ją pojmiesz, będziesz sięgać po nią przez cały czas. „Redukuje" tablicę do pojedynczej wartości — a ta wartość może być czymkolwiek: liczbą, obiektem, inną tablicą. Oto realistyczny przypadek użycia: budowanie mapy do wyszukiwania z tablicy:

js
// Group products by category (the pattern that makes reduce click)
const byCategory = products.reduce((acc, product) => {
  const cat = product.category;
  if (!acc[cat]) acc[cat] = [];
  acc[cat].push(product);
  return acc;
}, {}); // starting value is an empty object

// byCategory.electronics → [Wireless Keyboard, Mechanical Keyboard, USB-C Hub, Monitor Arm]
// byCategory.furniture   → [Standing Desk, Desk Lamp]

// Build an id → product lookup (O(1) access instead of .find() on every render)
const productById = products.reduce((acc, p) => {
  acc[p.id] = p;
  return acc;
}, {});

const keyboard = productById[2]; // instant lookup

// Calculate total cart value
const cart      = [{ productId: 1, qty: 2 }, { productId: 4, qty: 1 }];
const cartTotal = cart.reduce((total, item) => {
  const product = productById[item.productId];
  return total + (product.price * item.qty);
}, 0);
// 79.99 * 2 + 499.99 * 1 = 659.97
Wskazówka: Jeśli używasz reduce() tylko do sumowania liczb, rozważ czystszą alternatywę: products.reduce((sum, p) => sum + p.price, 0) sprawdza się w prostych przypadkach. Ale do grupowania i indeksowania reduce() jest niezastąpione.

find() i findIndex() — zatrzymaj się przy pierwszym trafieniu

Bardzo częstym błędem jest używanie filter(), gdy potrzebujesz tylko jednego elementu. filter() zawsze skanuje całą tablicę. find() zatrzymuje się zaraz po znalezieniu trafienia — O(1) w najlepszym przypadku vs O(n) dla filter:

js
// ❌ Returns an array, scans everything even after finding a match
const found = products.filter(p => p.id === 3)[0];

// ✅ Returns the item directly, stops at first match
const product = products.find(p => p.id === 3);
// { id: 3, name: 'USB-C Hub', ... }

// findIndex() — gives you the position (useful for updates and deletions)
const idx = products.findIndex(p => p.id === 3);
// Update immutably:
const updated = [
  ...products.slice(0, idx),
  { ...products[idx], inStock: true },
  ...products.slice(idx + 1)
];

some() i every() — sprawdzenia logiczne

Gdy potrzebujesz odpowiedzi tak/nie na temat zawartości tablicy, some() i every() są czystsze niż filtrowanie i sprawdzanie długości:

js
const hasOutOfStock   = products.some(p => !p.inStock);    // true
const allHighRated    = products.every(p => p.rating >= 4.0); // true
const allInStock      = products.every(p => p.inStock);       // false

// Common pattern: form validation
const formFields = [
  { name: 'email',    value: '[email protected]', valid: true  },
  { name: 'password', value: '',                 valid: false },
  { name: 'username', value: 'dev123',           valid: true  }
];

const isFormValid  = formFields.every(field => field.valid);   // false
const hasAnyError  = formFields.some(field => !field.valid);   // true

flat() i flatMap() — obsługa zagnieżdżonych tablic

Gdy API zwraca zagnieżdżone tablice, flat() i flatMap() spłaszczają je do jednego poziomu. flatMap() jest szczególnie przydatna, gdy operacja map może zwrócić zero, jeden lub kilka elementów dla każdego wejścia:

js
// flat() — collapse one level of nesting
const orderLines = [
  ['Wireless Keyboard', 'USB-C Hub'],
  ['Standing Desk'],
  ['Mechanical Keyboard', 'Monitor Arm', 'Desk Lamp']
];
const allItems = orderLines.flat();
// ['Wireless Keyboard', 'USB-C Hub', 'Standing Desk', 'Mechanical Keyboard', ...]

// flatMap() — map + flat in one pass (more efficient than chaining)
const ordersWithTags = [
  { id: 101, items: ['keyboard', 'hub'],   tags: ['electronics'] },
  { id: 102, items: ['desk', 'lamp'],      tags: ['furniture', 'sale'] },
];

// Get all unique tags across all orders
const allTags = ordersWithTags.flatMap(order => order.tags);
// ['electronics', 'furniture', 'sale']

// Filter-and-extract in one pass with flatMap
const expensiveNames = products.flatMap(p =>
  p.price > 100 ? [p.name] : [] // return empty array to skip, or [value] to include
);
// ['Mechanical Keyboard', 'Standing Desk']

Array.from() — konwersja obiektów podobnych do tablic

Array.from() konwertuje dowolną iterowalną strukturę na prawdziwą tablicę. Pojawia się to nieustannie przy listach węzłów DOM, zbiorach Set, mapach Map i wynikach generatorów:

js
// Convert a NodeList to an array so you can use .map() and .filter()
const checkboxes = Array.from(document.querySelectorAll('input[type="checkbox"]'));
const checkedValues = checkboxes
  .filter(el => el.checked)
  .map(el => el.value);

// Deduplicate an array using Set → Array.from
const tags    = ['electronics', 'sale', 'electronics', 'new', 'sale'];
const unique  = Array.from(new Set(tags));
// ['electronics', 'sale', 'new']

// Create a range (like Python's range())
const range = Array.from({ length: 5 }, (_, i) => i + 1);
// [1, 2, 3, 4, 5]

// Extract Map entries for further processing
const priceMap = new Map(products.map(p => [p.id, p.price]));
const prices   = Array.from(priceMap.values()); // [79.99, 149.99, ...]

Poprawne sortowanie

Domyślny sort() konwertuje wszystko na ciągi znaków, co oznacza, że liczby są sortowane błędnie, a sortowanie ciągów zawodzi dla znaków spoza ASCII. Zawsze przekazuj komparator:

js
// ❌ Default sort — wrong for numbers
[10, 9, 100, 2].sort(); // [10, 100, 2, 9] ← string order

// ✅ Numeric sort
[10, 9, 100, 2].sort((a, b) => a - b); // [2, 9, 10, 100] ascending
[10, 9, 100, 2].sort((a, b) => b - a); // [100, 10, 9, 2] descending

// Sort products by price ascending
const byPrice = [...products].sort((a, b) => a.price - b.price);

// Sort by name — use localeCompare for proper string ordering
const byName = [...products].sort((a, b) =>
  a.name.localeCompare(b.name, 'en', { sensitivity: 'base' })
);

// Multi-key sort: category first, then rating descending
const sorted = [...products].sort((a, b) => {
  if (a.category !== b.category) return a.category.localeCompare(b.category);
  return b.rating - a.rating;
});
Uwaga: sort() mutuje oryginalną tablicę. Zawsze najpierw skopiuj ([...products].sort(...)), jeśli chcesz zachować oryginalną kolejność.

Object.groupBy() — grupowanie w ES2024

Przed ES2024 do grupowania tablic używało się reduce() (jak pokazano wcześniej). Teraz jest wbudowana metoda: Object.groupBy(). Jest czystsza w prostych przypadkach grupowania:

js
// Group products by category — ES2024
const grouped = Object.groupBy(products, p => p.category);
// {
//   electronics: [Wireless Keyboard, Mechanical Keyboard, USB-C Hub, Monitor Arm],
//   furniture:   [Standing Desk, Desk Lamp]
// }

// Group by stock status
const byStock = Object.groupBy(products, p => p.inStock ? 'available' : 'unavailable');

// Group orders by month
const orders = [
  { id: 1, date: new Date('2026-01-15'), total: 129.99 },
  { id: 2, date: new Date('2026-01-22'), total: 49.99  },
  { id: 3, date: new Date('2026-02-05'), total: 89.99  },
];
const byMonth = Object.groupBy(orders, o =>
  o.date.toLocaleString('en', { month: 'long', year: 'numeric' })
);

Object.groupBy() jest dostępne w Node.js 21+ i wszystkich nowoczesnych przeglądarkach od połowy 2024 roku. Sprawdź dokumentację groupBy na MDN, aby uzyskać aktualne informacje o kompatybilności. W starszych środowiskach wzorzec z reduce() nadal działa.

Przydatne narzędzia

Podczas pracy z tablicami danych JSON z API te narzędzia oszczędzają naprawdę dużo czasu: JSON Formatter do inspekcji głęboko zagnieżdżonych danych, JSON Path do zapytań o konkretne pola z dużych tablic oraz JS Formatter do porządkowania kodu z łańcuchami metod. Pełna dokumentacja Array na MDN jest warta dodania do zakładek — jest tam więcej metod, niż wie większość programistów.

Podsumowanie

Metody tablicowe JavaScript pokrywają większość tego, po co sięgałoby się po bibliotekę narzędziową. map() i filter() do transformacji i podzbioru, reduce() do grupowania i indeksowania, find() zamiast filter()[0] przy wyszukiwaniu, flatMap() do filtrowania i transformacji w jednym przejściu oraz Object.groupBy() do czystego grupowania w nowoczesnych środowiskach. Kluczem jest dobór właściwego narzędzia — i świadomość, że większość pętli można zastąpić dobrze dobraną metodą.