📦 Cos'è un Array — una lista ordinata di valori
Un Array è una collezione ordinata di valori, accessibili tramite un indice numerico che parte sempre da 0. A differenza di Set, un array può contenere valori duplicati e l'ordine di inserimento è sempre garantito e accessibile per posizione.
const corsi = ['HTML', 'CSS', 'JavaScript'];
console.log(corsi[0]); // → 'HTML' (il primo elemento ha indice 0, non 1!)
console.log(corsi[2]); // → 'JavaScript'
console.log(corsi.length); // → 3 (numero totale di elementi)
console.log(corsi[corsi.length - 1]); // → 'JavaScript' (modo standard per ottenere l'ultimo elemento)
⚠️ Gli indici partono da 0, non da 1! Un array con 3 elementi ha indici validi 0, 1, 2 — provare ad accedere a corsi[3] restituisce undefined, non un errore.
➕ Aggiungere e rimuovere elementi
const carrello = ['mouse', 'tastiera'];
carrello.push('monitor'); // aggiunge IN FONDO: ['mouse','tastiera','monitor']
carrello.unshift('cavo'); // aggiunge ALL'INIZIO: ['cavo','mouse','tastiera','monitor']
const ultimo = carrello.pop(); // rimuove e restituisce l'ULTIMO: 'monitor'
const primo = carrello.shift(); // rimuove e restituisce il PRIMO: 'cavo'
console.log(carrello); // → ['mouse', 'tastiera']
💡 push/pop lavorano sulla fine dell'array (più efficienti), unshift/shift lavorano sull'inizio (richiedono di "spostare" tutti gli altri elementi, quindi più lenti su array molto grandi).
✂️ splice — inserire o rimuovere in un punto qualsiasi
const lista = ['a', 'b', 'c', 'd'];
// splice(indiceInizio, quantiRimuovere, elementiDaInserire...)
lista.splice(1, 2); // rimuove 2 elementi da indice 1: ['a', 'd']
const lista2 = ['a', 'd'];
lista2.splice(1, 0, 'b', 'c'); // inserisce senza rimuovere: ['a','b','c','d']
⚠️ splice() modifica l'array ORIGINALE (a differenza di slice, che ne crea uno nuovo) — attenzione a non confondere i due metodi dal nome simile ma comportamento diverso.
🔄 map() — trasformare ogni elemento in qualcos'altro
map() crea un nuovo array applicando una funzione a ogni elemento dell'array originale, che resta invariato. È probabilmente il metodo array più usato nel JavaScript moderno.
const prezzi = [10, 20, 30];
const prezziConIva = prezzi.map(p => p * 1.22);
console.log(prezziConIva); // → [12.2, 24.4, 36.6]
console.log(prezzi); // → [10, 20, 30] (l'originale NON viene modificato)
💡 Regola d'oro: map() restituisce SEMPRE un array della stessa lunghezza dell'originale — un elemento in ingresso produce sempre esattamente un elemento in uscita.
🎯 filter() — selezionare solo alcuni elementi
filter() crea un nuovo array contenente solo gli elementi per cui la funzione passata restituisce true.
const voti = [18, 25, 30, 15, 28];
const promossi = voti.filter(v => v >= 18);
console.log(promossi); // → [18, 25, 30, 28] (15 è escluso)
✅ A differenza di map(), filter() può restituire un array PIÙ CORTO dell'originale (o anche vuoto) — perché scarta gli elementi che non passano il test.
🔗 Combinare map e filter in catena
const prodotti = [
{ nome: 'Mouse', prezzo: 15, disponibile: true },
{ nome: 'Tastiera', prezzo: 40, disponibile: false },
{ nome: 'Monitor', prezzo: 200, disponibile: true }
];
const nomiDisponibili = prodotti
.filter(p => p.disponibile)
.map(p => p.nome);
console.log(nomiDisponibili); // → ['Mouse', 'Monitor']
💡 Questo "chaining" (filtra, poi trasforma) è un pattern estremamente comune: prima riduci l'array a ciò che ti serve con filter, poi trasformalo con map — molto più leggibile di un ciclo for con if annidati.
🧮 reduce() — condensare l'array in un unico valore
reduce() è il metodo più potente ma anche più complesso da capire: "riduce" l'intero array a un singolo valore (un numero, una stringa, anche un oggetto), accumulando un risultato ad ogni passaggio.
const prezzi = [10, 20, 30];
const totale = prezzi.reduce((accumulatore, valoreCorrente) => {
return accumulatore + valoreCorrente;
}, 0); // 0 è il valore iniziale dell'accumulatore
console.log(totale); // → 60
💡 Come leggerlo passo-passo: parte da accumulatore=0. Al primo giro: 0+10=10. Al secondo: 10+20=30. Al terzo: 30+30=60. Il risultato finale (60) è ciò che reduce restituisce.
🛒 Esempio pratico e-commerce: calcolare il totale di un carrello
const carrello = [
{ nome: 'Mouse', prezzo: 15, quantità: 2 },
{ nome: 'Tastiera', prezzo: 40, quantità: 1 }
];
const totaleCarrello = carrello.reduce((tot, item) => {
return tot + (item.prezzo * item.quantità);
}, 0);
console.log(totaleCarrello); // → 70 (15*2 + 40*1)
✅ Questo è l'uso da manuale di reduce nel mondo reale: calcolare un totale di carrello, una media voti, un conteggio aggregato — qualsiasi cosa che "condensa" una lista in un unico numero.
🔍 find() e findIndex() — cercare un singolo elemento
const utenti = [
{ id: 1, nome: 'Marco' },
{ id: 2, nome: 'Giulia' }
];
const utente = utenti.find(u => u.id === 2);
console.log(utente); // → { id: 2, nome: 'Giulia' } (l'oggetto trovato, o undefined se non c'è)
const indice = utenti.findIndex(u => u.id === 2);
console.log(indice); // → 1 (la posizione nell'array, o -1 se non trovato)
💡 find() restituisce l'ELEMENTO che soddisfa la condizione (o undefined), findIndex() restituisce la sua POSIZIONE (o -1) — usa il primo quando ti serve il dato, il secondo quando ti serve sapere "dove" si trova.
✅❌ some() e every() — verifiche booleane sull'intero array
const voti = [18, 25, 30, 15];
console.log(voti.some(v => v === 30)); // → true (ALMENO UN elemento soddisfa la condizione)
console.log(voti.every(v => v >= 18)); // → false (NON TUTTI gli elementi soddisfano — 15 no)
✅ some risponde a "c'è almeno un caso che...?", every risponde a "vale per tutti che...?" — entrambi restituiscono sempre un booleano, mai gli elementi stessi.
🔤 sort() — ordinare un array
const numeri = [40, 5, 100, 25];
console.log(numeri.sort()); // → [100, 25, 40, 5] SBAGLIATO! sort() di default ordina come STRINGHE
// Per ordinare numeri correttamente serve una funzione di confronto:
console.log(numeri.sort((a, b) => a - b)); // → [5, 25, 40, 100] crescente, corretto
console.log(numeri.sort((a, b) => b - a)); // → [100, 40, 25, 5] decrescente
⚠️ Il bug più comune con sort(): senza una funzione di confronto, JavaScript converte i numeri in stringhe e li ordina alfabeticamente — "100" viene prima di "25" perché '1' < '2' alfabeticamente. Serve SEMPRE (a,b) => a-b per numeri.