- Pubblicato il
Funzioni di Ordine Superiore (HOF) in JavaScript
- Autori
- Name
- Maico Orazio
- @mainick
Le funzioni di ordine superiore sono funzioni che utilizzano le funzioni come argomento o come valore di ritorno. L'uso delle funzioni in entrambi i ruoli non è necessario, basta in uno dei due casi, per diventare una funzione di ordine superiore.
Le funzioni JavaScript, map
, filter
e reduce
sono esempi di funzioni integrate di ordine superiore.
map
Funzione La funzione map
crea un nuovo array popolato con i risultati di una funzione di callback passata come argomento. Prende tutti i valori restituiti dalla funzione di callback e li archivia in un nuovo array.
La funzione di callback da passare a map
accetta tre argomenti:
- elemento
- indice
- array
Ad esempio, abbiamo un array di numeri e vogliamo creare un nuovo array che conterrà ogni elemento del primo array moltiplicato per 10. Risolviamo il problema con e senza una funzione di ordine superiore:
const num = [10, 20, 30]
// funzione normale
const newNum = []
for (let i = 0; i < num.length; i++) {
newNum.push(num[i] * 10)
}
console.log(newNum) // [100, 200, 300]
// funzione di ordine superiore map()
const newNum2 = num.map((item) => item * 10)
console.log(newNum2) // [100, 200, 300]
Dalla funzione di ordine superiore map
puoi vedere che possiamo ottenere lo stesso risultato con meno codice e una migliore struttura.
filter
Funzione La funzione filter()
crea un nuovo array popolato di tutti gli elementi che hanno superato la condizione della funzione di callback; anche qui la funzione di callback accetta tre parametri:
- elemento
- indice
- array
Ad esempio, supponiamo di avere un array contenente oggetti di studenti che seguono un corso e lo stato se hanno frequentato o meno le lezioni; dobbiamo filtrare l'array per recuperare solo gli studenti che hanno frequentato:
const students = [
{ name: 'Maico Orazio', status: true },
{ name: 'Giovanni Rossi', status: false },
{ name: 'Giuseppe Verdi', status: true },
]
// funzione normale
const presentStudents = []
for (let i = 0; i < students.length; i++) {
if (students[i].status === true) {
presentStudents.push(students[i])
}
}
console.log(presentStudents) // [{name:'Maico Orazio',status:true},{name:'Giuseppe Verdi',status:true}]
// funzione di ordine superiore filter()
const presentStudents2 = students.filter((student) => student.status === true)
console.log(presentStudents2) // [{name:'Maico Orazio',status:true},{name:'Giuseppe Verdi',status:true}]
Considera che abbiamo bisogno di un sottoinsieme di dati filtrando su più valori di proprietà. Possiamo farlo utilizzando filter
che contiene più condizioni:
const newFiltered = students.filter(
(student) => student.name === 'Maico Orazio' && student.status === true
)
console.log(newFiltered) // [{name:'Maico Orazio',status:true}]
Quando di filtra su più valori, l'espressione della funzione può diventare lunga, il che rende poco leggibile. Un modo per affrontare questo problema consiste nell'utilizzare più funzioni filter()
al posto dell'operatore logico &&
, ottenendo gli stessi risultati:
const newFiltered2 = students
.filter((student) => student.name === 'Maico Orazio')
.filter((student) => student.status === true)
console.log(newFiltered2) // [{name:'Maico Orazio',status:true}]
Un altro modo per esprimere un filtro complesso è creare una funzione denominata:
const studentsAttending = (student) => student.name === 'Maico Orazio' && student.status === true
const newFiltered3 = students.filter(studentsAttending)
console.log(newFiltered3) // [{name:'Maico Orazio',status:true}]
Possiamo ottimizzare la flessibilità consentendo di impostare il nome dello studente in fase di esecuzione utilizzando un parametro:
const studentsAttending = (student, name) => student.name === name && student.status === true
const newFiltered3 = students.filter(studentsAttending('Maico Orazio')) // Error
Sfortunatamente, questo creerebbe un errore perché il filtro si aspetta una funzione e ora stiamo cercando di passare l'output di studentsAttending
.
Curry in JavaScript
Per fornire una soluzione, possiamo utilizzare una tecnica avanzata di programmazione funzionale chiamata currying. Il currying consente di tradurre una funzione con più argomenti in una seguenza di funzioni, consentendoci così di creare parità con altre firme di funzione.
Il currying è una trasformazione di funzioni che traduce una funzione da richiamabile f(a, b, c)
in richiamabile come f(a)(b)(c)
.
Spostiamo il parametro name
in un'espressione di funzione e riscriviamo studentsAttending
usando il currying. In questo modo, la funzione studentsAttending
diventa una funzione che accetta un nome name
e restituisce un'altra funzione che accetta un oggetto student
:
const studentsAttending = (name) => (student) => student.name === name && student.status === true
const newFiltered3 = students.filter(studentsAttending('Maico Orazio'))
console.log(newFiltered3) // [{name:'Maico Orazio',status:true}]
reduce
Funzione Questo metodo esegue una funzione di callback su ogni elemento dell'array, e accetta due argomenti:
- funzione di callback
- valore iniziale
La funzione di callback accetta i seguenti quattro parametri:
- valore accumulatore: risultato dell'iterazione precedente
- valore corrente
- indice attuale
- array di origine
Ecco un esempio, in cui sommiamo tutti gli elementi di un array:
const nums = [10, 23, 45, 37, 101]
//funzione normale
const sum = 0
for (let i = 0; i < nums.length; i++) {
sum = sum + nums[i]
}
console.log(sum) // 216
// funzione di ordine superiore reduce()
const sum2 = nums.reduce((acc, value) => {
acc + value
})
console.log(sum2) // 216
Invece di sommare i numeri di un array, utilizziamo reduce
per trovare il numero più grande:
const nums = [10, 23, 45, 37, 101]
const max = nums.reduce((acc, value) => (acc > value ? acc : value))
console.log(max) // 101
Da tutti gli esempi precedenti, puoi vedere che le funzioni di ordine superiore rendono il codice più pulito e più facile da comprendere.
Creazione della nostra funzione di ordine superiore
Finora, ho mostrato solo esempi di funzioni di ordine superiore di funzioni integrate in JavaScript; ora, tuffiamoci nella creazione della nostra.
Creeremo un clone della funzione map
. Ad esempio, abbiamo un array contenente nomi, vogliamo ottenere la lunghezza di ogni nome usando la funzione di ordine superiore che creeremo:
function mapClone(arr, fn) {
const nameList = []
for (let i = 0; i < arr.length; i++) {
nameList.push(fn(arr[i]))
}
return nameList
}
La funzione maClone
appena creata accetta un array arr
e una funzione di callback fn
. Il ciclo for
scorre l'array dato in input e invoca la funzione di callback su ogni elemento.
const names = ['Maico', 'Giovanni', 'Giuseppe']
const nameLength = mapClone(names, (item) => item.length)
console.log(nameLength) // [ 5, 8, 8 ]
Buon lavoro 👨💻