Gli array sono la struttura dati fondamentale in JavaScript. Che tu stia trasformando risposte API, filtrando risultati di ricerca o aggregando dati di analytics, utilizzerai i metodi degli array decine di volte al giorno. Eppure, molti sviluppatori ne sfruttano solo una frazione, affidandosi ai cicli for quando una singola riga dichiarativa sarebbe più pulita, più veloce da leggere e meno soggetta a errori.

Questa guida offre un'immersione approfondita in ogni metodo principale degli array JavaScript, con esempi pratici e reali che puoi copiare immediatamente nei tuoi progetti.

forEach — Itera Senza Restituire

forEach esegue una funzione di callback per ogni elemento dell'array. Non restituisce un nuovo array, rendendolo ideale per effetti collaterali come il logging, la manipolazione del DOM o l'aggiunta a una struttura dati esterna.

forEach — Logging dei nomi utente
const utenti = [
  { nome: 'Alice', ruolo: 'admin' },
  { nome: 'Bob', ruolo: 'editor' },
  { nome: 'Carol', ruolo: 'viewer' }
];

utenti.forEach((utente, indice) => {
  console.log(`${indice + 1}. ${utente.nome} (${utente.ruolo})`);
});
// 1. Alice (admin)
// 2. Bob (editor)
// 3. Carol (viewer)

Dettaglio chiave: Non puoi interrompere un ciclo forEach prematuramente. Se hai bisogno di terminazione anticipata, usa invece for...of o some.

map — Trasforma Ogni Elemento

map crea un nuovo array applicando una funzione di trasformazione a ogni elemento. L'array originale non viene mai modificato. Questo è uno dei metodi più utilizzati in React, Vue e in qualsiasi pipeline di elaborazione dati.

map — Estrazione e trasformazione dati
const prodotti = [
  { nome: 'Tastiera', prezzo: 75 },
  { nome: 'Mouse', prezzo: 40 },
  { nome: 'Monitor', prezzo: 350 }
];

// Crea stringhe pronte per la visualizzazione
const etichettePrezzo = prodotti.map(
  p => `${p.nome}: $${p.prezzo.toFixed(2)}`
);
// ['Tastiera: $75.00', 'Mouse: $40.00', 'Monitor: $350.00']

// Estrai solo i prezzi
const prezzi = prodotti.map(p => p.prezzo);
// [75, 40, 350]

filter — Seleziona Elementi Che Superano un Test

filter restituisce un nuovo array contenente solo gli elementi per cui la funzione di callback restituisce true. È il sostituto dichiarativo delle istruzioni if all'interno dei cicli.

filter — Trovare prodotti costosi
const costosi = prodotti.filter(p => p.prezzo > 50);
// [{ nome: 'Tastiera', prezzo: 75 }, { nome: 'Monitor', prezzo: 350 }]

// Concatenamento di filter con map
const nomiCostosi = prodotti
  .filter(p => p.prezzo > 50)
  .map(p => p.nome);
// ['Tastiera', 'Monitor']

reduce — Accumula in un Singolo Valore

reduce è il coltellino svizzero dei metodi degli array. Itera sull'array, passando un accumulatore attraverso ogni passaggio. Il risultato può essere un numero, una stringa, un oggetto o persino un altro array.

reduce — Sommare prezzi e raggruppare dati
// Somma tutti i prezzi
const totale = prodotti.reduce((somma, p) => somma + p.prezzo, 0);
// 465

// Raggruppa utenti per ruolo
const raggruppati = utenti.reduce((acc, utente) => {
  acc[utente.ruolo] = acc[utente.ruolo] || [];
  acc[utente.ruolo].push(utente.nome);
  return acc;
}, {});
// { admin: ['Alice'], editor: ['Bob'], viewer: ['Carol'] }

// Costruisci una mappa di ricerca
const lookup = prodotti.reduce((mappa, p) => {
  mappa[p.nome.toLowerCase()] = p.prezzo;
  return mappa;
}, {});
// { tastiera: 75, mouse: 40, monitor: 350 }

Suggerimento: Fornisci sempre un valore iniziale (il secondo argomento di reduce). Ometterlo fa sì che il primo elemento venga usato come accumulatore iniziale, il che porta a bug sottili quando l'array è vuoto.

find & findIndex — Individua un Singolo Elemento

find restituisce il primo elemento che soddisfa il predicato, o undefined se nessuno corrisponde. findIndex restituisce invece l'indice, o -1.

find & findIndex
const ordini = [
  { id: 'ORD-001', stato: 'spedito' },
  { id: 'ORD-002', stato: 'in attesa' },
  { id: 'ORD-003', stato: 'consegnato' }
];

const inAttesa = ordini.find(o => o.stato === 'in attesa');
// { id: 'ORD-002', stato: 'in attesa' }

const indiceInAttesa = ordini.findIndex(o => o.stato === 'in attesa');
// 1

Entrambi i metodi interrompono l'iterazione non appena viene trovata una corrispondenza, rendendoli più efficienti di filter quando hai bisogno di un solo risultato.

some & every — Test Booleani sugli Array

some restituisce true se almeno un elemento supera il test. every restituisce true solo se tutti gli elementi lo superano. Entrambi interrompono presto l'esecuzione — smettono di iterare non appena la risposta è determinata.

some & every — Controlli di validazione
const punteggi = [82, 91, 76, 95, 88];

const c'èFallimento = punteggi.some(s => s < 60);
// false

const tuttiPromossi = punteggi.every(s => s >= 70);
// true

// Pratico: verifica se qualche campo del modulo è vuoto
const campi = ['Alice', '[email protected]', ''];
const haVuoti = campi.some(f => f.trim() === '');
// true

includes & indexOf — Verifica la Presenza

includes restituisce un booleano che indica se l'array contiene un dato valore. Utilizza l'algoritmo SameValueZero, il che significa che può rilevare NaN — a differenza di indexOf, che non può.

includes vs indexOf
const ruoli = ['admin', 'editor', 'viewer'];

ruoli.includes('admin');   // true
ruoli.indexOf('admin');    // 0

// Rilevamento NaN
[1, 2, NaN].includes(NaN);  // true
[1, 2, NaN].indexOf(NaN);   // -1 (non trova NaN)

flat & flatMap — Appiattisci Array Annidati

flat crea un nuovo array con gli elementi dei sotto-array concatenati fino a una profondità specificata. flatMap combina map e flat(1) in un unico passaggio, il che è sia più leggibile che più performante quando devi mappare e poi appiattire di un livello.

flat & flatMap
const annidato = [[1, 2], [3, [4, 5]], [6]];

annidato.flat();    // [1, 2, 3, [4, 5], 6]  — profondità 1
annidato.flat(2);   // [1, 2, 3, 4, 5, 6]    — profondità 2
annidato.flat(Infinity); // appiattisce tutti i livelli

// flatMap — dividi frasi in parole
const frasi = ['ciao mondo', 'foo bar baz'];
const parole = frasi.flatMap(s => s.split(' '));
// ['ciao', 'mondo', 'foo', 'bar', 'baz']

// flatMap — filtra e trasforma in un unico passaggio
const numeri = [1, 2, 3, 4, 5];
const raddoppiati = numeri.flatMap(n => n > 3 ? [n * 2] : []);
// [8, 10]  — agisce come filtro + map combinati

sort — Ordina Elementi

sort ordina l'array sul posto e restituisce l'array ordinato. Senza un comparatore, gli elementi vengono convertiti in stringhe e ordinati in ordine Unicode — che quasi mai è ciò che desideri per i numeri.

sort — Ordinamento numerico e di stringhe corretto
// SBAGLIATO: ordinamento stringa predefinito per numeri
[10, 9, 100].sort();
// [10, 100, 9]  — ordinato come stringhe!

// CORRETTO: comparatore numerico
[10, 9, 100].sort((a, b) => a - b);
// [9, 10, 100]

// Ordina oggetti per proprietà
prodotti.sort((a, b) => a.prezzo - b.prezzo);

// Ordinamento stringhe case-insensitive
const nomi = ['banana', 'Mela', 'ciliegia'];
nomi.sort((a, b) => a.localeCompare(b));
// ['Mela', 'banana', 'ciliegia']

Attenzione: sort modifica l'array originale. Se necessiti di un ordinamento immutabile, usa toSorted() (ES2023) o prima lo spread: [...arr].sort().

Metodi Nuovi da Conoscere (ES2023+)

Le recenti versioni ECMAScript hanno introdotto controparti non mutanti dei classici metodi mutanti:

  • toSorted() — restituisce un nuovo array ordinato senza modificare l'originale
  • toReversed() — restituisce un nuovo array invertito
  • toSpliced(start, deleteCount, ...items) — restituisce un nuovo array con splice applicato
  • with(index, value) — restituisce un nuovo array con un elemento sostituito
  • findLast() / findLastIndex() — cerca dalla fine dell'array
ES2023 — Operazioni su array immutabili
const originale = [3, 1, 4, 1, 5];

const ordinato = originale.toSorted((a, b) => a - b);
// ordinato: [1, 1, 3, 4, 5]
// originale: [3, 1, 4, 1, 5]  — invariato!

const sostituito = originale.with(2, 99);
// sostituito: [3, 1, 99, 1, 5]
// originale: [3, 1, 4, 1, 5]  — invariato!

Considerazioni sulle Performance

I metodi funzionali degli array sono espressivi e leggibili, ma comportano un overhead che dovresti comprendere:

  1. Il concatenamento crea array intermedi. arr.filter(...).map(...) itera l'array due volte e crea un array temporaneo. Per dataset molto grandi, un singolo reduce o un ciclo for può essere significativamente più veloce.
  2. sort è O(n log n). Evita di ordinare all'interno di cicli o di riordinare a ogni rendering. Memorizza i risultati ordinati quando possibile.
  3. find e some interrompono presto l'esecuzione. Preferiscili a filter(...)[0] o filter(...).length > 0 quando devi solo verificare l'esistenza di un elemento.
  4. flat(Infinity) può essere costoso. Se conosci la profondità di annidamento, specificala esplicitamente.
  5. Evita di creare funzioni all'interno di cicli intensivi (hot loops). Definisci le funzioni di callback al di fuori del ciclo o usa riferimenti a funzioni per una migliore ottimizzazione JIT.
Performance — Reduce a passaggio singolo vs metodi concatenati
// Più lento: due passaggi + array intermedio
const risultato = bigArray
  .filter(item => item.active)
  .map(item => item.value);

// Più veloce: passaggio singolo
const risultato = bigArray.reduce((acc, item) => {
  if (item.active) acc.push(item.value);
  return acc;
}, []);

Pattern Comuni e Ricette

Rimuovere Duplicati

Valori unici
const unici = [...new Set([1, 2, 2, 3, 3, 3])];
// [1, 2, 3]

// Oggetti unici per chiave
const utentiUnici = utenti.filter(
  (utente, i, arr) => arr.findIndex(u => u.nome === utente.nome) === i
);

Dividere un Array in Blocchi (Chunking)

Dividi in blocchi di N
function chunk(arr, size) {
  return Array.from(
    { length: Math.ceil(arr.length / size) },
    (_, i) => arr.slice(i * size, i * size + size)
  );
}

chunk([1, 2, 3, 4, 5], 2);
// [[1, 2], [3, 4], [5]]

Somma, Min, Max

Utility di aggregazione
const nums = [4, 2, 9, 1, 7];

const sum = nums.reduce((a, b) => a + b, 0);   // 23
const min = Math.min(...nums);                   // 1
const max = Math.max(...nums);                   // 9
const avg = sum / nums.length;                   // 4.6

Riepilogo

Padroneggiare i metodi degli array JavaScript ti consente di scrivere codice più dichiarativo, facile da testare e meno incline a errori di indice. Inizia con i tre principali — map, filter, reduce — e incorpora gradualmente find, some, every, flat e le nuove varianti immutabili ES2023. Comprendi i compromessi delle performance in modo da poter prendere decisioni informate sui percorsi critici (hot paths), e mantieni il tuo codice pulito e leggibile ovunque altro.

Ottimizza il Tuo JavaScript

Scrivi codice JavaScript pronto per la produzione? Usa le utility gratuite di Pan Tool per minimizzare il tuo codice per il deployment o "abbellire" script di terze parti per una migliore leggibilità.