Frontend

Operatori e strutture dati moderni in JavaScript

Autore

Manuel Ricci

JavaScript, uno dei linguaggi di programmazione più versatili, si è evoluto notevolmente negli anni. Questo approfondimento esplora in profondità le strutture dati Set, Map, WeakMap, WeakSet e alcuni operatori moderni, fornendo esempi pratici per una migliore comprensione.

Set

Il Set in JavaScript è una collezione di elementi unici, che può contenere sia valori primitivi che oggetti.

Caratteristiche Dettagliate

  • Unicità: Ogni valore in un Set è unico, il che elimina automaticamente i duplicati.
  • Accesso non indicizzato: A differenza degli array, i Set non permettono l'accesso diretto ai loro elementi tramite indici.
  • Metodi Utili:
    • .add(value): Aggiunge un valore al Set.
    • .delete(value): Rimuove un valore specificato.
    • .has(value): Verifica se un valore è presente nel Set.

Esempio Approfondito

1let numeri = new Set([2, 4, 6, 6, 8]);
2numeri.add(10); // Aggiunge 10
3numeri.delete(2); // Rimuove 2
4console.log(numeri.has(4)); // true
5
6// Iterazione su un Set
7for (let numero of numeri) {
8  console.log(numero); // Output: 4, 6, 8, 10
9}

Utilizzi Avanzati

  • Rimozione efficace di duplicati da array.
  • Implementazione di strutture dati come stack e code, dove l'unicità è fondamentale.

Map

Un Map in JavaScript è una struttura dati che memorizza coppie chiave-valore, con chiavi uniche di qualsiasi tipo.

Caratteristiche Dettagliate

  • Chiavi Versatili: A differenza degli oggetti, che hanno chiavi stringa, un Map può avere chiavi di qualsiasi tipo.
  • Ordine Mantenuto: A differenza degli oggetti, i Map mantengono l'ordine di inserimento delle chiavi.
  • Metodi Fondamentali:
    • .set(key, value): Aggiunge o aggiorna una coppia chiave-valore.
    • .get(key): Ritorna il valore associato a una chiave.
    • .has(key): Verifica se una chiave è presente nel Map.

Esempio Approfondito

1let mappa = new Map();
2mappa.set('nome', 'Alice');
3mappa.set('età', 25);
4
5console.log(mappa.get('nome')); // "Alice"
6console.log(mappa.size); // 2
7
8// Iterazione su una Map
9for (let [chiave, valore] of mappa) {
10  console.log(`${chiave}: ${valore}`); // "nome: Alice", "età: 25"
11}

Utilizzi Avanzati

  • Gestione efficiente di dati strutturati.
  • Implementazione di cache per memorizzare e recuperare dati velocemente.

WeakMap

Un WeakMap è una variante speciale di Map in cui tutte le chiavi sono oggetti e sono debolmente referenziate.

Caratteristiche Dettagliate

  • Chiavi Deboli: Le chiavi in un WeakMap sono oggetti e non impediscono al garbage collector di rimuovere questi oggetti quando non sono più referenziati altrove.
  • Non Enumerabile: A differenza di Map, non è possibile elencare le chiavi di un WeakMap.
  • Uso della Memoria: Migliorato per la gestione di grandi quantità di dati.

Esempio Approfondito

1let weakMap = new WeakMap();
2let oggetto = { id: 1 };
3weakMap.set(oggetto, 'informazioni aggiuntive');
4
5console.log(weakMap.get(oggetto)); // "informazioni aggiuntive"
6oggetto = null; // Lascia che il garbage collector rimuova l'oggetto se non è referenziato altrove

#

Utilizzi Avanzati

  • Ottimale per memorizzare dati privati associati a un oggetto.
  • Utilizzato in librerie e framework per mantenere metadati senza influire sul ciclo di vita degli oggetti.

WeakSet

Un WeakSet è un insieme di oggetti con riferimenti deboli.

Caratteristiche Dettagliate

  • Solo Oggetti: Può contenere solamente oggetti, non valori primitivi.
  • Riferimenti Deboli: Gli oggetti in un WeakSet possono essere rimossi dal garbage collector se non sono più referenziati.
  • Non Iterabile: A differenza di Set, non è possibile iterare attraverso un WeakSet.

Esempio Approfondito

1let weakSet = new WeakSet();
2let oggetto1 = { nome: 'oggetto1' };
3weakSet.add(oggetto1);
4
5console.log(weakSet.has(oggetto1)); // true
6oggetto1 = null; // L'oggetto può essere rimosso dal garbage collector

Utilizzi Avanzati

  • Gestione di collezioni di oggetti senza influenzare il garbage collection.
  • Utilizzato in contesti dove si desidera evitare perdite di memoria per riferimenti non necessari.

Operatori Moderni

JavaScript offre una varietà di operatori moderni per semplificare le operazioni comuni.

Destructuring Assignment

Permette di scomporre array e oggetti assegnando le loro parti a variabili distinte.

Esempio Avanzato

1let [a, , c] = [1, 2, 3]; // 'a' è 1, 'c' è 3
2let { nome, età } = { nome: 'Alice', età: 25, lavoro: 'Ingegnere' }; // 'nome' è 'Alice', 'età' è 25

Spread Operator (...)

Espande elementi di array o oggetti in nuovi contesti.

Esempio Avanzato

1let parteIniziale = [1, 2];
2let arrayCompleto = [...parteIniziale, 3, 4]; // [1, 2, 3, 4]
3let oggetto = { nome: 'Alice', età: 25 };
4let copiaOggetto = { ...oggetto, lavoro: 'Ingegnere' }; // { nome: 'Alice', età: 25, lavoro: 'Ingegnere' }

Rest Operator (...)

Raccoglie elementi in un array, specialmente in funzioni con un numero variabile di argomenti.

Esempio Avanzato

1function unisciStringhe(separator, ...stringhe) {
2  return stringhe.join(separator);
3}
4console.log(unisciStringhe("-", "Alice", "Bob", "Charlie")); // "Alice-Bob-Charlie"

Operatori Logici Avanzati

Operatore AND Logico (&&)

L'operatore && ritorna il valore del primo operando se è falsy (valore che equivale a false, come 0, null, undefined, false, NaN, o una stringa vuota), altrimenti ritorna il valore del secondo operando. Questo comportamento è noto come "short-circuiting".

Esempio

1let risultato = 0 && "test"; // 0, perché il primo operando è falsy
2let nome = "Alice" && "Bob"; // "Bob", perché il primo operando è truthy

Operatore OR Logico (||)

L'operatore || ritorna il valore del primo operando se è truthy, altrimenti ritorna il valore del secondo operando. Anche questo comporta un "short-circuiting".

Esempio

1let risultato = 0 || "test"; // "test", perché il primo operando è falsy
2let nome = "Alice" || "Bob"; // "Alice", perché il primo operando è truthy

Operatore Nullish Coalescing (??)

Questo operatore ritorna il secondo operando solo quando il primo è null o undefined, altrimenti ritorna il primo. È utile per assegnazioni predefinite.

Esempio

1let valore;
2let defaultValore = valore ?? "predefinito"; // "predefinito", perché valore è undefined
3valore = 0;
4defaultValore = valore ?? "predefinito"; // 0, perché valore è definito (anche se falsy)

Concatenazione Opzionale

La concatenazione opzionale (?.) permette di accedere in modo sicuro alle proprietà di un oggetto che potrebbe non esistere. Se l'oggetto prima dell'operatore ?. è null o undefined, l'espressione si interrompe e ritorna undefined, altrimenti procede normalmente.

Esempio

1let oggetto = { a: { b: { c: 1 } } };
2let valoreC = oggetto.a?.b?.c; // 1, perché oggetto.a e oggetto.a.b esistono
3let valoreInesistente = oggetto.a?.b?.d; // undefined, perché oggetto.a.b.d non esiste
4
5// Senza l'uso di concatenazione opzionale, potrebbe essere generato un errore
6// let errore = oggetto.a.b.d; // TypeError se oggetto.a o oggetto.a.b non esistono

Utilizzi Avanzati

  • Accesso sicuro a catene di proprietà profonde in oggetti.
  • Riduzione del rischio di errori di tipo TypeError in accessi a proprietà di oggetti non definiti.

Gli operatori logici &&, ||, ??, insieme alla concatenazione opzionale ?., offrono strumenti potenti per scrivere codice più sicuro, leggibile e conciso. Essi consentono di gestire in modo elegante situazioni in cui i dati potrebbero essere incompleti o incerti, che sono comuni nella programmazione di applicazioni reali.

Caricamento...

Diventiamo amici di penna? ✒️

Iscriviti alla newsletter per ricevere una mail ogni paio di settimane con le ultime novità, gli ultimi approfondimenti e gli ultimi corsi gratuiti puubblicati. Ogni tanto potrei scrivere qualcosa di commerciale, ma solo se mi autorizzi, altrimenti non ti disturberò oltre.

Se non ti piace la newsletter ti ricordo la community su Discord, dove puoi chiedere aiuto, fare domande e condividere le tue esperienze (ma soprattutto scambiare due meme con me). Ti aspetto!

Ho in previsione di mandarti una newsletter ogni due settimane e una commerciale quando capita.