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.
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.
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.
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.
// 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.
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.
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ò.
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.
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.
// 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'originaletoReversed()— restituisce un nuovo array invertitotoSpliced(start, deleteCount, ...items)— restituisce un nuovo array con splice applicatowith(index, value)— restituisce un nuovo array con un elemento sostituitofindLast()/findLastIndex()— cerca dalla fine dell'array
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:
- Il concatenamento crea array intermedi.
arr.filter(...).map(...)itera l'array due volte e crea un array temporaneo. Per dataset molto grandi, un singoloreduceo un cicloforpuò essere significativamente più veloce. sortè O(n log n). Evita di ordinare all'interno di cicli o di riordinare a ogni rendering. Memorizza i risultati ordinati quando possibile.findesomeinterrompono presto l'esecuzione. Preferiscili afilter(...)[0]ofilter(...).length > 0quando devi solo verificare l'esistenza di un elemento.flat(Infinity)può essere costoso. Se conosci la profondità di annidamento, specificala esplicitamente.- 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.
// 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
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)
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
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à.