51 Destructuring , operatore rest

Il destructuring è una nuova caratteristica di ES6 che permette di estrarre informazioni che sono incapsulate in una struttura come un oggetto o un array.

Ecco un oggetto le cui property rappresentano i dati di un ipotetico prodotto:

let prodotto = 
  { codice: "BPX001", categoria: "alimentari", prezzo: 1.25 };

Se volessimo assegnare i dati a variabili esterne, fino ad ora, dovremmo comandare manualmente l’assegnamento

let codice = prodotto.codice;

Dovrei fare altrettanto per tutte le altre proprietà che volessi estrarre.

Tramite il destructuring abbiamo la possibilità di creare una sintassi dove al posto di una singola variabile, metto uno schema (pattern) che va ad estrarre i valori dall’oggetto e li inserisce in variabili con lo stesso nome

let {codice, prezzo} = prodotto;

Questa è la forma compatta del destructuring, dove viene estratto il valore della proprietà codice dell’oggetto prodotto e viene inserito in una variabile denominata codice. Analogamente per la proprietà prezzo.

Quindi le variabili isolate hanno lo stesso identificatore delle property dell’oggetto, pertanto ritroverò il valore di prodotto.codice dentro ad una variabile codice, andiamo a stampare

writeln(`${codice} - ${prezzo}` );

verrà stampato il BPX001 – 1.25 .

Oltre alla forma abbreviate esiste anche quella estesa che ci permetterà di scegliere il nome assegnato alla variabili

let {codice: il_codice, prezzo: il_prezzo} = prodotto;
writeln(`${il_codice} - ${il_prezzo}` );

Il risultato della stampa è il medesimo.

Da notare l’uso del backtick (apice inclinato ` ) che su windows si ottiene con ALT96, mentre sul Mac ALT9, che permette di calcolare delle espressioni iniettate tra $ e parentesi graffe, all’interno di normali stringhe. ${il_codice} verrà sostituito col suo valore BPX001.

Destructuring su array

Immaginiamo una lettura di temperature ogni tot di ore:

let temperature =[1,3,6,9,8,5,4,-1];

abbiamo estratto le varie temperature in varie ore

let [h00, h3, h6, h9, h12, h15, h18,h21] = temperature;

I vari h corrispondono ai momenti delle letture. A questo punto posso procedere alla stampa

writeln(`Temp. alle h06:00 ${h6}℃; alle h18:00 ${h18}℃`);

Ecco una stampa esempio della temperatura alle sei del mattino e alle sei di sera.

Valore multiplo

Un altra situazione derivata è quella di una funzione che restituisce un valore multiplo, per esempio sempre riferito alle temperature, vogliamo registrare la temperatura minima e massima

let pos_min=0; let pos_max=0;

Immaginiamo un algoritmo che determina le posizioni dell’elemento minimo e massimo e restituisce per esempio questi valori:

pos_min=3; pos_max=7;

quindi viene restituito un array con 2 elementi

return [pos_min, pos_max];

ecco la funzione completa min_max()

function min_max(vettore)
{
  let pos_min=0; let pos_max=0;

  //immaginiamo qui l`algoritmo che determina le 
  //posizioni dell`elemento minimo e massimo
  pos_min=3; pos_max=7;
 
  return [pos_min, pos_max];
}

a questo punto dove si richiama la funzione, posso usare al volo il destructuring, facendo entrare i dati dall’aria precedente temperature[]

let [pos_temp_min, pos_temp_max] = min_max(temperature);

in questo caso si è separato nelle variabili generate al volo dal destructuring pos_temp_min il valore minimo e pos_temp_max il valore massimo, per poi utilizzarle nelle stampe

writeln(`Temperatura minima alle ${3*pos_temp_min}`);
writeln(`Temperatura massima alle ${3*pos_temp_max}`);

la moltiplicazione per 3 è dovuta al fatto che viene restituita la posizione dell’array, quindi avendo un avanzamento di 3 ore per ogni scansione della temperatura,  alla posizione 2, per es, corrisponderebbe alle ore 6.

Destructuring su oggetti annidati

dato l’oggetto libro con le sue proprietà autore e titolo, la proprietà autore è a sua volta un altro oggetto con le sue proprietà cognome e nome

let libro = {autore: {cognome: "Alessandro", nome:"Manzoni"},
             titolo: "I promessi sposi"};

andiamo a destrutturare con la forma abbreviata, seguendo i livelli degli oggetti interni dove destruttureremo a loro volta

let { autore: {cognome, nome}, titolo} = libro;

ecco la stampa

writeln(cognome);
writeln(titolo);

Se volessi destrutturare solo su una proprietà, per esempio mi interessa estrarre nuovamente il titolo

let {titolo} = libro;

otterrei un errore perché la variabile titolo è già stata assegnata nella destrutturazione precedente, potrei farlo con la forma estesa, assegnando un nuovo identificatore alla variabile

let {titolo: t2} = libro;   
writeln(t2);

fino ad esso abbiamo sempre assegnato il destructuring creando una nuova variabile con let possiamo assegnare però i dati ad una variabile già esistente

let s = "";

seguendo il ragionamento di prima se scrivessi

let {titolo : s } = libro;

otterrei l’errore di variabile s già dichiarata, togliendo il let, Andrea a comandare l’uso di una variabile già esistente

{titolo: s} = libro ;

Otterrei comunque un errore sintattico, in quanto questa struttura con parentesi graffe e uguale, non è ammessa in questa maniera, basta allora racchiudere il tutto tra parentesi tonde che è l’operatore usato per far valutare un’espressione

({titolo: s} = libro);

a questo punto l’interpreta capisce che la parte tra graffe non è un blocco, ma un pattern ed esegue l’operazione correttamente

writeln(s);

Con gli array il problema non sussiste, perché è ancora più semplice grazie alla loro sintassi con le quadre

let t=0;
[t] = temperature;
writeln(t);

e avrò la stampa della temperatura letta a mezzanotte.

Ecco invece come saltare elementi dell’array che non ci interessa estrarre, ogni virgola rappresenta l’elemento da ignorare

[,,,t] = temperature;
writeln(t);

potrebbe esserci il caso che manca un elemento nell’array

let v = [1,2];
let [,,z] = v;

genererebbe un errore, basta assegnare un valore di default

let v = [1,2];
let [,,z=0] = v;
writeln(z);

vediamo un altra forma

let [,,,...dalle_9_in_poi] = temperature ;

salta i primi 3 elementi, poi incontra l’operatore speciale rest rappresentato da 3 punti, che si può tradurre nel parlato comprensibile in: tutto ciò che avanza.

Andreamo a creare un sotto array dalle_9_in_poi[] con le sole rimanenti. stampiamolo con un for of:

for (temp of dalle_9_in_poi) writeln(temp);