de Guido Schmitz

Funcțiile de comandă superioară vă pot ajuta să vă intensificați jocul JavaScript, făcând codul mai declarativ. Adică scurt, simplu și lizibil.

O funcție de ordine superioară este orice funcție care returnează o funcție atunci când este executată, ia o funcție ca unul sau mai multe dintre argumentele sale, sau ambele. Dacă ați folosit oricare dintre Array metode precum map sau filter, sau a trecut o funcție de apel invers către jQuery $.get, ați lucrat deja cu funcțiile de ordine superioară.

Când folosești Array.map, furnizați o funcție ca singur argument, pe care o aplică fiecărui element conținut în matrice.

var arr = [ 1, 2, 3 ];

var arrDoubled = arr.map(function(num) {
  return num * 2;
});

console.log(arrDoubled); // [ 2, 4, 6 ]

Funcțiile de ordin superior pot, de asemenea, să returneze o funcție. De exemplu, puteți crea o funcție numită multiplyBy care ia un număr și returnează o funcție care înmulțește un alt număr pe care îl furnizați cu primul număr furnizat. Puteți utiliza această abordare pentru a crea un multiplyByTwo funcție la care să treacă Array.map. Acest lucru vă va oferi același rezultat pe care l-ați văzut mai sus.

function multiplyBy(num1) {
  return function(num2) {
    return num1 * num2;
  }
}

var multiplyByTwo = multiplyBy(2);

var arr = [ 1, 2, 3 ];

var arrDoubled = arr.map(multiplyByTwo);

console.log(arrDoubled); // [ 2, 4, 6 ]

Este esențial să știți când și cum să utilizați aceste funcții. Acestea vă fac codul mai ușor de înțeles și de întreținut. De asemenea, facilitează combinarea funcțiilor între ele. Aceasta se numește compoziție și nu voi merge în detaliu aici. În acest articol voi acoperi cele mai utilizate trei funcții de ordin superior în JavaScript. Acestea sunt .filter(), .map() și .reduce().

Filtru

Imaginați-vă că scrieți o bucată de cod care acceptă o listă de persoane în care doriți să filtrați persoanele care sunt egale sau peste vârsta de 18 ani.

Lista noastră arată ca cea de mai jos:

const people = [ { name: ‘John Doe’, age: 16 }, { name: ‘Thomas Calls’, age: 19 }, { name: ‘Liam Smith’, age: 20 }, { name: ‘Jessy Pinkman’, age: 18 },];

Să vedem un exemplu de funcție de primă ordine care selectează persoane care au peste 18 ani. Folosesc un funcția săgeată care face parte din standardul ECMAScript sau ES6 pe scurt. Este doar un mod mai scurt de a defini o funcție și vă permite să săriți funcția de tastare și să reveniți, precum și unele paranteze, paranteze și un punct și virgulă.

const peopleAbove18 = (collection) => {  const results = [];   for (let i = 0; i < collection.length; i++) {    const person = collection[i];     if (person.age >= 18) {      results.push(person);    }  }
  return results;};

Ce se întâmplă dacă vrem să selectăm toți oamenii care au între 18 și 20 de ani? Am putea crea o altă funcție.

const peopleBetween18And20 = (collection) => {  const results = [];   for (let i = 0; i < collection.length; i++) {    const person = collection[i];     if (person.age >= 18 && person.age <= 20) {      results.push(person);    }  }
  return results;};

Este posibil să recunoașteți deja multe coduri repetate aici. Acest lucru ar putea fi abstractizat într-o soluție mai generalizată. Aceste două funcții au ceva în comun. Ambele repetă o listă și o filtrează într-o anumită condiție.

„O funcție de ordin superior este o funcție care ia una sau mai multe funcții ca argumente.”Closurebridge

Ne putem îmbunătăți funcția anterioară folosind o abordare mai declarativă, .filter().

const peopleAbove18 = (collection) => {  return collection    .filter((person) => person.age >= 18);}

Asta e! Putem reduce o mulțime de cod suplimentar folosind această funcție de comandă superioară. De asemenea, codul nostru este mai bine citit. Nu ne pasă cum sunt filtrate lucrurile, vrem doar să le filtreze. Voi intra în combinarea funcțiilor mai târziu în acest articol.

Hartă

Să luăm aceeași listă de oameni și o serie de nume care arată dacă persoanei îi place să bea cafea.

const coffeeLovers = [‘John Doe’, ‘Liam Smith’, ‘Jessy Pinkman’];

Modul imperativ va fi ca:

const addCoffeeLoverValue = (collection) => {  const results = [];   for (let i = 0; i < collection.length; i++) {    const person = collection[i];
    if (coffeeLovers.includes(person.name)) {      person.coffeeLover = true;    } else {      person.coffeeLover = false;    }     results.push(person);  }   return results;};

Am putea folosi .map() pentru a face acest lucru mai declarativ.

const incrementAge = (collection) => {  return collection.map((person) => {    person.coffeeLover = coffeeLovers.includes(person.name);     return person;  });};

Din nou, .map() este o funcție de înaltă ordine. Permite transmiterea unei funcții ca argument.

Reduce

Pun pariu că îți va plăcea această funcție atunci când știi când și cum să o folosești.
Interesant .reduce() este că majoritatea funcțiilor de mai sus pot fi realizate cu aceasta.

Să luăm mai întâi un exemplu simplu. Vrem să rezumăm toate vârstele oamenilor. Din nou, vom analiza cum se poate face acest lucru folosind abordarea imperativă. Practic, face o colecție prin colecție și crește o variabilă odată cu vârsta.

const sumAge = (collection) => {  let num = 0;   collection.forEach((person) => {    num += person.age;  });   return num;}

Și abordarea declarativă folosind .reduce().

const sumAge = (collection) => collection.reduce((sum, person) => { return sum + person.age;}, 0);

Putem chiar să folosim .reduce() pentru a crea propria noastră implementare a .map() și .filter() .

const map = (collection, fn) => {  return collection.reduce((acc, item) => {    return acc.concat(fn(item));  }, []);}
const filter = (collection, fn) => {  return collection.reduce((acc, item) => {    if (fn(item)) {      return acc.concat(item);    }     return acc;  }, []);}

Acest lucru ar putea fi greu de înțeles la început. Dar ce .reduce() practic, este să începeți cu o colecție și o variabilă cu o valoare inițială. Apoi iterați peste colecție și adăugați (sau adăugați) valorile variabilei.

Combinând harta, filtrarea și reducerea

Grozav, că aceste funcții există. Dar partea bună este că există pe prototipul Array în JavaScript. Aceasta înseamnă că aceste funcții pot fi utilizate împreună! Acest lucru facilitează crearea funcțiilor reutilizabile și reduce cantitatea de cod necesară pentru a scrie anumite funcționalități.

Așa că am vorbit despre utilizarea .filter() pentru a filtra persoanele egale sau sub vârsta de 18 ani. .map() pentru a adăuga coffeeLover proprietate și .reduce() pentru a crea în sfârșit o sumă a vârstei tuturor combinate.
Să scriem un cod care combină de fapt acești trei pași.

const people = [ { name: ‘John Doe’, age: 16 }, { name: ‘Thomas Calls’, age: 19 }, { name: ‘Liam Smith’, age: 20 }, { name: ‘Jessy Pinkman’, age: 18 },];
const coffeeLovers = [‘John Doe’, ‘Liam Smith’, ‘Jessy Pinkman’];
const ageAbove18 = (person) => person.age >= 18;const addCoffeeLoverProperty = (person) => { person.coffeeLover = coffeeLovers.includes(person.name);  return person;}
const ageReducer = (sum, person) => { return sum + person.age;}, 0);
const coffeeLoversAbove18 = people .filter(ageAbove18) .map(addCoffeeLoverProperty);
const totalAgeOfCoffeeLoversAbove18 = coffeeLoversAbove18 .reduce(ageReducer);
const totalAge = people .reduce(ageReducer);

Dacă o faci în mod imperativ, vei ajunge să scrii o mulțime de coduri repetate.

Mentalitatea de a crea funcții cu .map() ,.reduce() și .filter() va îmbunătăți calitatea codului pe care îl veți scrie. Dar, de asemenea, adaugă multă lizibilitate. Nu trebuie să vă gândiți la ce se întâmplă în interiorul unei funcții. Este ușor de înțeles.

Mulțumesc pentru lectură! 🙂

Salută Stare de nervozitate