Gli array JavaScript hanno una delle API di metodi più ricche di qualsiasi linguaggio principale. Ma la maggior parte dei tutorial insegna map e filter con esempi artificiosi — raddoppiare i numeri in un array, filtrare i numeri pari — e poi ti lasciano scoprire il resto. Analizziamo i metodi che compaiono davvero nel codice in produzione, usando dati realistici: prodotti, ordini e record utenti.

Il Dataset con cui lavoreremo

Per mantenere gli esempi concreti, useremo un catalogo prodotti realistico per tutto l'articolo:

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() — Trasformare ogni elemento

Array.prototype.map() crea un nuovo array applicando una funzione a ogni elemento. È il motore della trasformazione dei dati — rimodellare le risposte API nel formato necessario alla tua UI:

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() non muta mai l'array originale — restituisce sempre uno nuovo. Ecco perché è sicuro concatenarlo, e perché dovresti preferirlo a un ciclo for quando la trasformazione è l'obiettivo.

filter() — Ottenere un sottoinsieme

filter() restituisce un nuovo array contenente solo gli elementi per cui la callback restituisce 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() — Il coltellino svizzero

Array.prototype.reduce() è quello che gli sviluppatori evitano perché la firma sembra intimidatoria. Ma una volta che scatta, lo userai continuamente. "Riduce" un array a un singolo valore — e quel valore può essere qualsiasi cosa: un numero, un oggetto, un altro array. Ecco un caso d'uso realistico: costruire una mappa di ricerca da un array:

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
Consiglio pro: Se stai usando reduce() solo per sommare numeri, considera un'alternativa più pulita: products.reduce((sum, p) => sum + p.price, 0) va bene per i casi semplici. Ma per raggruppamenti e indicizzazioni, reduce() è imbattibile.

find() e findIndex() — Fermarsi al primo match

Un errore molto comune è usare filter() quando hai bisogno di un solo elemento. filter() scansiona sempre l'intero array. find() si ferma non appena trova una corrispondenza — O(1) nel caso migliore vs O(n) per 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() e every() — Controlli booleani

Quando hai bisogno di una risposta sì/no sul contenuto di un array, some() e every() sono più puliti del filtraggio e della verifica della lunghezza:

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() e flatMap() — Gestire gli array annidati

Quando la tua API restituisce array annidati, flat() e flatMap() li collassano in un unico livello. flatMap() è particolarmente utile quando un'operazione map potrebbe produrre zero, uno o più elementi per input:

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() — Convertire oggetti simili ad array

Array.from() converte qualsiasi iterabile in un array reale. Questo si presenta continuamente con NodeList DOM, Set, Map e risultati di generatori:

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, ...]

Ordinamento corretto

Il metodo predefinito sort() converte tutto in stringhe, il che significa che i numeri vengono ordinati in modo errato e l'ordinamento delle stringhe si rompe per i caratteri non ASCII. Passa sempre un comparatore:

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;
});
Attenzione: sort() muta l'array originale. Espandi sempre prima ([...products].sort(...)) se devi mantenere l'ordine originale.

Object.groupBy() — Raggruppamento ES2024

Prima di ES2024 si usava reduce() per raggruppare gli array (come mostrato in precedenza). Ora c'è un built-in: Object.groupBy(). È più pulito per i casi di raggruppamento semplice:

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() è disponibile in Node.js 21+ e in tutti i browser moderni dalla metà del 2024. Controlla il riferimento MDN per groupBy per la compatibilità attuale. Per gli ambienti più vecchi, il pattern con reduce() funziona ancora.

Strumenti utili

Quando lavori con array di dati JSON dalle API, questi strumenti fanno risparmiare tempo reale: JSON Formatter per ispezionare payload profondamente annidati, JSON Path per interrogare campi specifici da array grandi, e JS Formatter per pulire il codice con catene di metodi. Il riferimento MDN per Array vale la pena di essere salvato tra i preferiti — ci sono più metodi di quanti la maggior parte degli sviluppatori sappia.

In conclusione

I metodi degli array JavaScript coprono la maggior parte di ciò per cui si ricorrerebbe a una libreria di utilità. map() e filter() per trasformare e filtrare, reduce() per raggruppare e indicizzare, find() al posto di filter()[0] per le ricerche, flatMap() per filter-e-trasforma in un unico passaggio, e Object.groupBy() per raggruppamenti puliti negli ambienti moderni. La chiave è usare lo strumento giusto per il lavoro — e sapere che la maggior parte dei cicli può essere sostituita con un metodo ben scelto.