Programavimas

„JavaScript“ pamoka: aukštesnio lygio funkcijos

Praėjusią savaitę kalbėdamas apie atmintį, atsainiai atsisakiau termino „aukštesnės eilės funkcija“. Nors dabar jaučiuosi patogiai mėtydamasi tokiais terminais, ne visada žinojau, ką jie reiškia. Šią savaitę mes išnagrinėsime, kas yra aukštesnės eilės funkcijos, parodysime keletą pavyzdžių ir sužinosime, kaip kurti savo.

Savo esme aukštesnės eilės funkcija yra tik funkcija, kuri funkciją priima kaip argumentą arba grąžina funkciją. Tai įmanoma „JavaScript“ dėka pirmos klasės funkcijų, o tai reiškia, kad „JavaScript“ funkcijos gali būti perduotos kaip ir bet kuris kitas kintamasis. Nors tai skamba gana tiesmukai, jis ne visai telegrafuoja tokią galią, kokią turite su pirmos klasės funkcijomis.

Jei rašote „JavaScript“, tikriausiai naudojote aukštesnės eilės funkcijas ir net nepastebėjote. Jei kada nors pakeitėte a dėl ciklo su masyvo metodu, jūs naudojote aukštesnės eilės funkcijas. Jei kada nors naudojote AJAX skambučio rezultatus (be asinchroninis/laukti), naudojote aukštesnės eilės funkcijas (tiek pažadai, tiek atgaliniai skambučiai apima aukštesnės eilės funkcijas). Jei kada nors parašėte „React“ komponentą, kuriame rodomas elementų sąrašas, naudojote aukštesnės eilės funkcijas. Pažiūrėkime tuos pavyzdžius:

const elementai = ['a', 'b', 'c', 'd', 'e']

// Vietoj to, kad kilpa ....

už (tegul i = 0; i <elementai. ilgis - 1; i ++) {

console.log (punktai [i]);

}

// Mes galime naudoti aukštesnės eilės funkciją forEach

// (forEach ima funkciją kaip argumentą)

items.forEach ((item) => console.log (item));

// Atšaukimas ar pažadai, jei darote

// asinchroninės užklausos, kurias naudojate

// aukštesnės eilės funkcijos

gauti ('// aws.random.cat/meow', (atsakymas) => {

„putImageOnScreen“ (atsakymas.failas);

});

gauti ('// random.dog/woof.json').tada(( atsakymas) => {

„putImageOnScreen“ (atsakymas.failas);

});

// Žemiau esančiame „React“ komponente naudojamas žemėlapis,

// kuri yra aukštesnės eilės funkcija

const myListComponent = (rekvizitai) => {

grįžti (

   

    {props.items.map ((item) => {

    grįžti (

  • {item}
  • )

          })}

      );

    };

Tai yra aukštesnės eilės funkcijų, kurios priima funkcijas kaip argumentus, pavyzdžiai, tačiau daugelis jų grąžina ir funkcijas. Jei kada nors matėte funkcijos iškvietimą, kuriame yra du skliaustų rinkiniai, tai yra aukštesnės eilės funkcija. Tokie dalykai anksčiau buvo retesni, tačiau jei apskritai dirbate su „Redux“, tikriausiai naudojote Prisijungti funkcija, kuri yra aukštesnės eilės funkcija:

eksportuoti numatytąjį prisijungimą (mapStateToProps, mapDispatchToProps) („MyComponent“);

Aukščiau nurodytu atveju mes skambiname Prisijungti su dviem argumentais ir jis grąžina funkciją, kurią mes nedelsdami iškviečiame vienu argumentu. Jūs taip pat matėte (arba parašėte) paprastą registravimo biblioteką, kuri naudoja funkcijas kaip grąžinimo reikšmes. Toliau pateiktame pavyzdyje sukursime žurnalistą, kuris užregistruos kontekstą prieš pranešimą:

const createLogger = (kontekstas) => {

grąža (msg) => {

console.log (`$ {context}: $ {msg}`);

  }

};

const log = createLogger ('myFile');

žurnalas ('Labai svarbus pranešimas');

// atsijungia „myFile: labai svarbus pranešimas“

Aukščiau pateiktame pavyzdyje pradedama iliustruoti kai kurias aukštesnės eilės funkcijų galias (taip pat žr. Mano ankstesnį įrašą apie atmintį). Prisimink tai createLogger imasi argumento, kuriuo remiamės grąžinamos funkcijos kūne. Tą grąžintą funkciją, kurią priskiriame kintamajam žurnalasvis tiek gali pasiekti kontekste argumentas, nes funkcija buvo apibrėžta jo apimtyje.

Įdomus faktas: nuoroda kontekste yra įmanoma dėl uždarymų. Čia nesileisiu į uždarymus, nes jie nusipelno savo įrašo, tačiau juos galima naudoti kartu su aukštesnio lygio funkcijomis, norint gauti tikrai įdomių efektų.

Pavyzdžiui, uždarymų naudojimas kartu su aukštesnės eilės funkcijomis anksčiau buvo vienintelis būdas, kaip „JavaScript“ turėjome „privačius“ arba apsaugotus nuo klastojimo kintamuosius:

leiskite protectedObject = (funkcija () {

tegul myVar = 0;

grįžti {

gauti: () => myVar,

prieaugis: () => myVar ++,

  };

})();

protectedObject.get (); // grąžina 0

protectedObject.increment ();

protectedObject.get (); // grąžina 1

myVar = 42; // ohi! ką tik sukūrėte visuotinį kintamąjį

protectedObject.get (); // vis tiek grąžina 1

Vis dėlto nenusivilkime. Aukštesnio lygio funkcijoms nereikia nieko įmantraus, pavyzdžiui, uždarymo. Tai tiesiog funkcijos, kurios kitas funkcijas laiko argumentais arba kurios grąžina funkcijas. Pilnas sustojimas. Jei norite daugiau pavyzdžių ar daugiau skaityti, perskaitykite Marijn Haverbeke „Eloquent JavaScript“ skyrių apie aukštesnio lygio funkcijas.

Klausimai ar komentarai? Nedvejodami kreipkitės į „Twitter“: @freethejazz.