60 funzioni freccia (Fat Arrow Function)
Le funzioni frecce o fat arrow function, sono state introdotte con ECMAScript6 e sono molto utili per la loro sintassi diretta. Si dichiarando specificando degli argomenti facoltativi racchiusi tra parentesi tonde, seguite dal simbolo fat arrow => e il valore di ritorno
() => return 2;
vediamo una semplice funzione nella sua sintassi standard
let test = function() { return 2; } console.log(test());
ora lo stesso esempio con le funzioni freccia
let test2 = () => console.log(3); test2();
se devo passare degli argomenti, le parentesi tonde sono obbligatorie
let test2 = (arg1,arg2) => console.log(arg1,arg2); test2(4,5);
solo nel caso di un solo argomento si possono evitare le parentesi tonde, ma per una buona leggibilità del codice sono consigliate anche in questa situazione.
Nel caso di più istruzioni, il ritorno va racchiuso tra parentesi graffe
let test2 = (arg1,arg2) => { console.log(arg1,arg2); console.log(3); } test2(4,5);
Nel caso di 1 solo ritorno posso omettere le graffe, ma non devo mettere il return
let test2 = (arg1,arg2) => arg1 * arg2; console.log(test2(4,5));
invece se c’è più di un’espressione bisogna mettere esplicitamente il return, oltre che le graffe
let test2 = (arg1,arg2) => { console.log(arg1); return arg1 * arg2; } console.log(test2(4,5));
Filtrare un array
dato il seguente array di numeri
var arr = [2,5,7,9,6,8, 13,15];
vogliamo estrarre solo i numeri pari, vediamolo con il modo classico, utilizzando il metodo filter
var arrEven = arr.filter( function(ele){ return ele%2 ===0; } );
vediamolo con le funzioni arrow
arrEven = arr.filter( ele => ele%2 === 0)
come si nota il codice è nettamente più corto, pulito e leggibile. In entrambi i casi se voglio restituire un risultato dovrò seguire un’ istruzione, per esempio mandiamo in console i numeri estratti moltiplicati per 2 usando il metodo map
console.log(arrEven.map( ele => ele*2));
se invece ho più parametri, come detto prima, dovrò racchiuderli tra tonde, vediamolo con l’uso del metodo reduce
console.log(arrEven.reduce( (ele1, ele2)=> ele1*ele2));
Perdita del this
Le funzioni arrow, a differenza di quelle classiche che creano un loro this interno quando vengono istanziate, preservano l’ambiente (this) del blocco di codice dove vengono eseguite. In altre parole le funzioni arrow sono sempre funzioni anonime e il loro this fa sempre riferimento allo scope in cui si trova.
Vediamo nella pratica, creando un oggetto con 1 proprietà name e un metodo displayName
let obj = { name : 'Faghy', displayName : function() { console.log(this.name); } }; obj.displayName();
Questo è un banale esempio che stampa il nome e il this è riferito all’oggetto intero obj. Vediamo se dentro displayName aggiungiamo un funzione tipo setTimeout che lancia a sua volta una funzione dopo un tot di millisecondi
let obj = { name : 'Faghy', myName : 'Test Faghy', displayName : function() { setTimeout( function() { console.log('output=' + this.myName); } , 1000 ); } }; obj.displayName();
In questo caso ricevevamo un undefined perché il this con le funzioni classiche fa riferimento all’ambiente interno e quindi è riferito a setTimeout nel quale non viene trovata la proprietà myName.
Prima di ECMAScript6 si raggirava il problema aggiungendo prima una variabile che veniva inizializzata col valore this
let obj = { name : 'Faghy', myName : 'Test Faghy', displayName : function() { let self = this; setTimeout( function() { console.log('output=' + this.myName); } , 1000 ); } }; obj.displayName();
In questo modo il risultato ottenuto è quello voluto.
Vediamo adesso con le funzioni arrow:
let obj2 = { name : 'Faghy', myName : 'Test Faghy', displayName : function() { setTimeout( () => console.log('output=' + this.myName), 1000); } }; obj2.displayName();
Come si vede il codice oltre a essere più corto, è anche più chiaro e il this della funzione arrow
() => console.log('output=' + this.myName)
è riferito allo scope globale, cioè all’oggetto obj2, perché in realtà le funzioni arrow, che sono anonime, non hanno un this proprio e il this non viene riferito a loro, ma all’oggetto nel cui lo dichiarato.
Inoltre le funzioni arrow non hanno arguments.
In generale le arrow function sono da utilizzare quando è più corto scrivere il codice, tipo il caso di funzione anonima, per processare gli array o dove si perde lo scope del this come in quest’ultimo caso.