61 Parametri Rest
Prima di ECMAScript 6 non era possibile assegnare dei valori di default ad un parametro di una funzione.
Lo stratagemma che si poteva adottare era simile al seguente:
function isGreater( param1 , param2) { var param1 = param1 || 0; var param2 = param2 || 0; return param1 > param2; } console.log(isGreater());
Creavo una variabile, gli assegnavo il valore del parametro oppure ( or || ) un valore di default.
var param1 = param1 || 0;
In console viene restituito false, perché param1 è uguale a param2, se passo 2 valori col primo maggiore, ottengo TRUE
function isGreater( param1 , param2) { var param1 = param1 || 0; var param2 = param2 || 0; return param1 > param2; } console.log(isGreater( 3 , 2 ));
Da ECMAScript 6 non c’è più bisogno di fare tutto questo, si passa il valore di default direttamente
function isGreater( param1=0 , param2=0 ) { return param1 > param2; } console.log(isGreater());
Non è obbligatorio passare a tutti i parametri il valore di default, può essere assegnato anche solo ad un parametro, qualora il parametro che non ha un valore di default, viene considerato UNDEFINDED fino a che non ha un valore.
Operatore REST
Anche se l’abbiamo già incontrato nella lezione sul destructuring, vediamo un altro esempio di in questa sede, dove affrontiamo i cambiamenti di ECMAScript 6. Supponiamo di avere una funzione calc() che effettua un calcolo su una serie di parametri che passiamo:
function calc(operation, param1, param2, param3) { a = Array.prototype.slice.call(arguments, 1); console.log(a); } calc('+',2,3,4,5);
Dove il parametro operation costituiva un operazione dei vari parametri dichiarati dopo. Non sapendo a priori quanti parametri sarebbero stati passati, avrei dovuto utilizzare il metodo slice, il quale ci restituisce una porzione di un array in un range che possiamo specificare. restituiti, quindi dovevo andare ad applicare lo slice sul prototipo dell’array chiamando ( call ) arguments
a = Array.prototype.slice.call(arguments, 1);
Il secondo parametro indica la posizione dove deo terminare l’array , mentre il parametro indica l’inizio, nel nostro caso, arguments, è un oggetto speciale di javascript simile ad un array, che corrisponde ai parametri passati alla funzione
function calc(operation, param1, param2, param3) { a = Array.prototype.slice.call(arguments, 1); console.log(a); } calc('+',2,3,4,5);
Quindi utilizzando questo costrutto, qualsiasi parametro passato nel richiamo della funzione, sarebbe stato aggiunto
calc('+',2,6,4,5,8,11,234);
Utilizzando il REST parameter di ECMAScript 6, è possibile ovviare al meccanismo. Basta inserire 3 punti seguiti da un parametro finale che sarà poi richiamato
function calc2(operation, ...a)
Il primo parametro rimane quello dell’operazione, mentre il secondo è un parametro variabile preceduto dal rest parameter ( … ), a questo punto basta richiamare il parametro dopo il rest ( a ) per ottenere tutti i parametri passati, senza conoscerne il numero a priori o dover usare meccanismi particolari, con un codice nettamente più pulito:
function calc2(operation, ...a) { console.log(a); } calc2('+',11,9,1,4,262);
Diventa tutto molto più snello, quindi a questo punto completo il mio codice facendo effettuare realmente l’operazione di somma dei numeri passati. Per esempio posso utilizzare il metodo reduce sul parametro a (che grazia all’operatore rest contiene tutti i numeri passati). Reduce applica una funzione ai valori di un array. .
return a.reduce(function (x,y) { });
In questo esempio, reduce applica la funzione di callback, che nel nostro caso è una funzione anonima, perchè la costruiamo al volo, ai parametri dichiarati, ovvero x che sarà il valore passato dal richiamo della funzione e y il valore successivo. Reduce riduce l’array applicando la funzione su ogni parametro. Adesso costruiamo la funzione anonima utilizzando il metodo eval che esegue codice javascript ai parametri passati
return eval(x+operation+y);
In questo modo mi viene restituito il valore dell’operazione eseguita sui parametri passati
function calc2(operation, ...a) { return a.reduce(function (x,y) { return eval(x+operation+y) }); } let res = calc2('+',11,9,1,4,262); console.log(res);
Posso anche passare qualsiasi altro operatore come la sottrazione
let res = calc2('-',11,9,1,4,262);
In questo caso l’operazione iniziale che eval effettua sarebbe :
eval(11 + '-' + 9);
Eseguendo il nostro codice con la sottrazione otterrei -265
function calc2(operation, ...a) { return a.reduce(function (x,y) { return eval(x+operation+y) }); } let res = calc2('-',11,9,1,4,262); console.log(res);
Nell’applicazione pratica dovrei mettere un controllo sul tipo di operatore passato perchè eval è uno strumento molto potente, quindi lasciato senza nessun controllo di sicurezza potrebbe essere usato per creare danni allo script.