Ako već neko vrijeme programirate u JavaScriptu, sigurno ste čuli za... funkcije strelica i poznato posebno ponašanje ovoI također je vrlo vjerovatno da vam je glava eksplodirala više puta pokušavajući shvatiti zašto. ovo Jedna stvar se odnosi na normalnu funkciju, a nešto sasvim drugo na funkciju strelice.
Savladavanje ova dva koncepta nije samo stvar teorije: to je ključno za pisanje Moderni kod u JavaScriptu i ReactuRazumijevanje kako funkcionišu rukovaoci događajima, kako se kontekst ponaša unutar klasa, kako se asinhroni povratni pozivi rješavaju u Node.js-u i zašto se određeni obrasci danas smatraju dobrom praksom.
Prije svega: kratak pregled funkcija u JavaScriptu
U JavaScriptu možete deklarisati funkcije na nekoliko načina, i svaki način ima implikacije na to kako se one ponašaju. ovo, in obim i trenutno je funkcija dostupna u kodu.
Deklaracija funkcije
Klasična deklaracija funkcije koristi ključnu riječ Funkcija i ime. Ove vrste funkcija su "povišene" (dizanje) na početku opsega gdje su deklarisani, što omogućava pozivanje funkcije čak i prije njene definicije u datoteci.
U funkciji deklarisanoj na tradicionalan način, vrijednost ovo određuje se prema kako Funkcija se poziva: ako se poziva kao metoda objekta, ako se koristi sa novi, ako je u striktnom režimu, ako se prebacuje na poziv, primijeniti o vezatiitd. Ova fleksibilnost je moćna, ali je ujedno i izvor mnogih grešaka u složenom kodu.
Izraz funkcije
Također možete dodijeliti anonimnu ili imenovanu ulogu varijablaU tom slučaju, sama funkcija se ne pokreće, već se pokreće samo deklaracija varijable (sa ima), ali ne i njegovu vrijednost. Sa pustiti y const Ne možete ga čak ni koristiti prije njegove linije definicije zbog privremena mrtva zona.
Ove funkcije dijele isti model ova dinamika Za razliku od klasičnih deklaracija: njihova vrijednost uvijek ovisi o kontekstu pozivanja, tako da ostaju osjetljive na to kako ih prosljeđujete kao povratni poziv ili kako ih koristite unutar klasa i objekata.
Šta su tačno funkcije strelica?
Funkcije strelica su uvedene sa ECMAScript 2015 (ES6) kao praktičniji, kompaktniji i izražajniji način deklarisanja funkcija, posebno za povratne pozive i funkcionalno programiranje s metodama poput karta, Filter o Smanjiti.
Njegova osnovna sintaksa sastoji se od liste parametara, nakon kojih slijedi operator => a zatim jedan izražavanje ili a blok kodaOvaj kompaktni format čini kod efikasnijim. čitljiv u mnogim scenarijima gdje ste ranije morali pisati duge i repetitivne anonimne funkcije.
Osnovna sintaksa funkcija strelica
Funkcije sa strelicama podržavaju nekoliko varijacija sintakse, sve zasnovane na istim pravilima, ali sa prečicama za jednostavnije slučajeve. Razumijevanje svakog oblika pomaže vam da ih napišete. čistač kod Mogu brzo prepoznati šta svaki povratni poziv radi.
- Bez parametaraPrazne zagrade se koriste prije strelice, a obično se koristi izraz poslije.
const getMessage = () => "Hola"; - Jedan parametarMožete izostaviti zagrade oko naziva parametra, što kod čini sažetijim.
const square = x => x * x; - Nekoliko parametaraUvijek morate koristiti zagrade koje ih zatvaraju, odvojene zarezima.
const sum = (a, b) => a + b; - Tijelo jednog izrazaAko ne koristite vitičaste zagrade, izraz se vraća na određeni način. implicitno bez potrebe za pisanjem povratak.
- Višelinijski tekstAko koristite tipke, morate pisati povratak eksplicitno da vrati vrijednost, baš kao u normalnoj funkciji.
Uobičajeni izvor grešaka je zaboravljanje povratak Kada pređete sa verzije s jednim redom na tijelo s vitičastim zagradama kako biste dodali više logike, vaša funkcija odjednom počinje vraćati nedefinisan I nije očigledno zašto.
Funkcije strelica i literalni objekti
Ako funkcija strelice s jednim izrazom vrati doslovni objektMorate taj objekt staviti u zagrade kako ga mehanizam ne bi pomiješao s početkom funkcionalnog bloka. To je mala sintaksna zamka koja mnoge ljude iznenadi.
U suprotnom, interpreter interpretira ključeve kao prazan blok i vaša funkcija neće vratiti objekt, već nedefinisanOvo uzrokuje teško uočljive greške kada pokušate pristupiti svojstvima koja nikada nisu vraćena.
Funkcije strelica i njihovo ponašanje
Pravi faktor razlikovanja streličnih funkcija nije sintaksa, već njihova model ovogaDok tradicionalne funkcije imaju ova dinamika U zavisnosti od njihovih naziva, funkcije strelica imaju ovaj leksikonTo jest, oni hvataju Ovo je iz područja u kojem su stvoreni i drže ga nepromijenjenim.
To znači da unutar funkcije strelice, ovo Ne može se promijeniti sa poziv, primijeniti ni vezatiI ne zavisi od toga da li ga koristite kao povratni poziv u obrađivaču događaja ili ga prosljeđujete drugoj funkciji. Uvijek će imati istu vrijednost koju je imao izvan sebe u trenutku definicije.
Kako ovo funkcioniše u normalnim funkcijama?
U funkciji deklarisanoj sa Funkcija, vrijednost ovo Zavisi od konteksta:
- Ako funkciju pozovete kao metoda objekta, ovo Pokažite na taj objekat.
- Ako ga pozovete bez konteksta u nestriktnom režimu, ovo pozivanje na globalni objekat (prozor u pregledniku, globalno u Node.js-u).
- Ako koristite novi, ovo zatim ukazuje na novostvorena instanca.
- Ako se prijavite poziv, primijeniti o vezati, možete prisilno podesiti vrijednost ovo ručno do objekta po vašem izboru.
U striktnom režimu, ako pozovete normalnu funkciju bez objekta kao prijemnika i bez korištenja poziv ili slično, ovo će biti nedefinisanZato se u mnogim modernim primjerima vide funkcije koje počinju sa 'use strict' kako bi se izbjegle tihe greške i prisililo na dosljednije ponašanje.
Kako ovo funkcioniše u funkcijama strelica?
U slučaju funkcija strelica, ovo Ne preračunava se prilikom pozivanja; uzima se direktno iz područje gdje su definiraniTo jest, ponašaju se slično kao što se varijable hvataju zatvaranjem (zatvaranje): Gledaju prema van i zauvijek pamte tu vrijednost.
Ovo ima nekoliko veoma važnih posljedica za vaš svakodnevni život:
- Ne možete koristiti funkciju strelice kao što je graditelj con novijer nemaju svoje ovo niti odgovarajući prototip.
- Pozivanje funkcije strelice sa poziv o primijeniti neće promijeniti vrijednost ovoMeđutim, ostatak argumenata ćete moći proslijediti normalno.
- U metodama objekata kreiranih kao funkcije strelica, ovo Neće pokazivati na objekat, već na gornji okoliš (na primjer, prozor ili modul), što je gotovo uvijek greška.
Ključna stvar je da su funkcije strelica idealne kada želite da Ovaj unutrašnji je isti kao i vanjski.Ali su loša ideja kada ti treba metoda stvarnog objekta ili kada namjeravate kreirati instancu nečega pomoću novi.
Funkcije strelica, klase i React

U svetu reagovati i JavaScript klasa općenito, rukovanje ovo To je osjetljivo pitanje. Komponente klase naslijeđene od React.Component Oni koriste metode u kojima ovo mora dosljedno pokazivati na instancu komponente kako bi se pristupilo this.props y ovo.stanje.
S metodama definiranim korištenjem klasične sintakse klase, vrijednost ovo Može se "izgubiti" prilikom prosljeđivanja metode kao povratnog poziva događaja, na primjer onClickZato ćete u mnogim starijim tutorijalima vidjeti obrasce poput this.metodo.bind(this) u konstruktoru ili direktno u JSX-u, nešto što se danas smatra prilično opširnim.
Tipični obrasci povezivanja u Reactu
U komponenti klase, historijski su postojala četiri glavna načina da se to osigura ovo uvijek pokazuje na komponentu kada se pozove iz rukovaoca događajima:
- Usar vezati u metodi renderovati, što osigurava kontekst, ali kreira novu funkciju pri svakom renderiranju.
- Napravite povezivanje u konstruktoru kako bi se izbjeglo ponovno kreiranje funkcije iznova i iznova, održavajući jednu referencu.
- Definišite rukovatelja kao svojstvo klase sa funkcijom strelice, koristeći činjenicu da funkcije strelica obuhvataju ovo instance.
- Koristite Funkcija strelice ugrađena u JSX, direktno prosljeđujući funkciju strelice atributu onClick ili ekvivalent.
U praksi, opcija da se rukovatelj deklarira kao svojstvo klase pomoću funkcije strelice To je postao najpogodniji obrazac: pišete manje koda, izbjegavate potrebu za vezati priručnik i ovo Uvijek težite komponenti bez iznenađenja.
Funkcije strelica u komponentama funkcija
Dolaskom funkcionalne komponente i kukeReact se mnogo više oslanja na funkcije strelica. Većina modernih komponenti je implementirana kao strelice. const MojaKomponenta = () => { … }Ovo čini upotrebu funkcija strelica prirodnom i konzistentnom u cijelom stablu.
Unutar ovih komponenti, uobičajeno je kombinirati funkcije strelica s drugim ES6 funkcijama kao što su destrukturiranje, literali šablona, ternarni operatori, širenje i metode niza poput karta, Filter y Smanjiti, čime se konstruira vrlo ekspresivna sintaksa, ali ona koja zahtijeva dobro rukovanje kontekstom i nepromjenjivost.
Ovo u globalnom kontekstu, pojedinačni objekti i funkcije
Da bismo razumjeli zašto funkcije strelica toliko mijenjaju igru, vrijedi pogledati kako se ponašaju. ovo u različitim izvornim JavaScript kontekstima, kako u pregledniku tako i u Node.js-u.
U globalni opseg preglednika, izvan bilo koje funkcije ili modula, ovo pokažite na objekat prozorTo znači da je svaka varijabla deklarisana sa ima Na višem nivou, on se oslanja na taj globalni objekt i dostupan je i po imenu i po naziv_prozoraOvo se smatra lošom praksom u složenim primjenama zbog globalnog zagađenja.
ovo unutar doslovnih objekata
Kada definirate doslovni objekt Kod tradicionalnih metoda, svaka metoda dobija ovo koji se odnosi na sam objekat prilikom njegovog pozivanja kao obj.method()Ovo je standardni način pristupa sestrinskim nekretninama sa ovo.svojstvo bez potrebe za posrednim varijablama.
Problem nastaje kada ove metode zamijenite sa funkcije strelicaPošto nemamo ovaj vlastitiFunkcija strelice će uhvatiti eksterni `this`, koji je vjerovatno globalni ili modularni `this`. Kao rezultat toga, nećete moći pristupiti svojstvima objekta unutar metode koristeći ovo, potpuno kršeći prvobitnu namjeru dizajna.
Ovo je unutar labavih funkcija i strogog načina rada
U tradicionalnim funkcijama koje se nazivaju "unplugged", bez prijemnog objekta, vrijednost ovo Zavisi od toga da li se kod nalazi u strogi način Ili ne. Strogo govoreći, to se vraća nazad u globalni objekat, dok strogo govoreći postaje eksplicitno nedefinisankako bi se izbjegle opasne akcije po globalnu okolinu.
Ovo ponašanje se drastično mijenja kada enkapsulirate svoj kod u ES module, moderne pakete ili IIFE-ove, gdje globalno može biti drugačije ili nije vezano za ovo na uobičajen način, posebno u node.js, gdje je glavni opseg arhive onaj od modul a ne onu globalnu.
poziv, primjena, povezivanje i njihov odnos s ovim
JavaScript nudi tri široko korištene metode u odnosu na klasične funkcije za upravljanje kontekstom: poziv, primijeniti y vezatiSvi oni vam omogućavaju da eksplicitno kontrolišete koju vrijednost uzima. ovo kada se funkcija izvrši.
Ove metode funkcionišu samo sa funkcije deklarirane s funkcijom (ili ekvivalente), budući da funkcije strelica ignoriraju svaki pokušaj promjene njihovog `this`. Zato su sve tri toliko korisne pri radu sa starijim API-jima, starim klasama ili obrascima gdje želite ponovo koristiti istu funkciju na različitim objektima.
pozovite i primijenite: pozovite s eksplicitnim ovim
tako poziv como primijeniti odmah izvršavaju funkcijuJedina razlika je u načinu na koji prosljeđujete argumente. U oba slučaja, prvi parametar koji prosljeđujete je objekt koji treba konvertirati. ovo unutar funkcije.
con poziv Sljedeći argumenti su navedeni jedan po jedan, dok sa primijeniti Oni se predstavljaju kao arrayOvo se odlično uklapa u situacije u kojima već imate listu argumenata kao kolekciju i želite je ubaciti takvu kakva jeste u poziv.
bind: kreiraj novu funkciju sa `this` setom
Metoda vezati Trenutno ne izvršava funkciju, već umjesto toga generira nova funkcija sa ovo trajno povezano objektu koji odredite. To je kao da kreirate "specijalizovanu" verziju originala koja će se uvijek ponašati unutar tog konteksta.
Ovaj obrazac je vrlo uobičajen za prosljeđivanje metoda objekata API-jima koji će ih kasnije pozivati, na primjer kao povratne pozive događaja, bez gubitka originalnog konteksta. Prije popularizacije funkcija strelica, vezati To je bio jedan od najčistijih načina da se osigura da metoda klase nastavi pokazivati na ispravnu instancu.
Zašto su funkcije sa strelicama idealne za povratne pozive?
Jedan od razloga zašto su funkcije strelica osvojile JavaScript ekosistem je njihova pogodnost za asinhroni povratni pozivi i funkcionalno programiranje. Prilikom rada s API-jima kao što su setTimeout, setInterval, obećanja Ili sa petljom događaja Node.js, često vam je potreban pristup vanjskom kontekstu bez njegovog iskrivljavanja.
Prije ES6, korišteni su trikovi poput spremanja const self = this o konstanta to = ovo prije ulaska u povratni poziv, tako da se ispravan objekt i dalje može referencirati iz funkcije. Funkcije strelica čine ovo nepotrebnim automatskim hvatanjem Ovaj vanjski i sačuvajte ga.
Funkcije strelica i petlja događaja u Node.js-u
En node.js, oko kojeg se vrti većina zanimljivog koda Asinhroni ulazno/izlazni procesi (datoteke, mreža, tajmeri), kombinacija funkcija strelica sa modelom petlja događaja i redovi povratnih poziva To mnogo pojednostavljuje život. Svaki put kada proslijedite funkciju poput handler-a fs.readFileBez obzira da li šaljete HTTP serveru ili bilo kojoj libuv operaciji, funkcije strelica pomažu da reference na susjedne varijable i kontekste modula budu bez iznenađenja.
Nadalje, u redovima mikrozadataka kao što su oni od obećanja o process.nextTickVrlo je uobičajeno pisati kratke povratne funkcije poput onda o ulov sa sintaksom strelice, koristeći prednosti oba implicitni povratak kao ovaj leksikon, što kod čini deklarativnijim i izražajnijim.
Kada NE biste trebali koristiti funkcije sa strelicama?
Iako se funkcije strelica mogu činiti kao magično rješenje za sve probleme, postoje scenariji u kojima je njihova upotreba direktno kontraproduktivno pa čak i generira greške koje je teško otkriti.
Jedan od njih, možda i najvažniji, su metode objekata ili klasa kojima je potrebno vlastito `this`Drugo je kada želite kreirati graditelji ili koristiti objektno orijentisane obrasce podržane prototipovima i nasljeđivanjem, gdje odsustvo prototip a vlastiti kontekst znači da funkcije strelica jednostavno ne odgovaraju.
Izbjegavajte korištenje funkcija strelica kao metoda objekta.
Ako definirate metodu objekta pomoću funkcije strelice, Ovaj interni element se neće odnositi na objekatveć kontekstu u kojem je taj objekt definiran. Ovo krši očekivanja svakoga ko čita kod i namjerava ga koristiti ovo.svojstvo unutar metode.
Preporučeni način pisanja metoda koje zavise od ovo Radi se o nastavku korištenja klasične sintakse u literalnim objektima ili deklarisanju tih metoda na standardan način u klasama, rezervirajući funkcije strelica za interne povratne pozive koji trebaju uhvatiti ovo iz superiorne metode.
Ne koristite funkcije strelica kao konstruktore
Nedostaju funkcije strelica [[Konstrukcija]], interni mehanizam koji omogućava pozivanje funkcije sa noviStoga, pokušaj njihovog korištenja kao konstruktora generirat će TypeErrorNi oni nemaju svoje. prototipStoga ne možete obustaviti dijeljene metode za instance.
Ako vaš dizajn zahtijeva instance za višekratnu upotrebu sa zajedničkim svojstvima i metodama, trebali biste se odlučiti za časovi ili tradicionalnim konstruktorskim funkcijama, ostavljajući funkcije strelica za logiku bez stanja ili čisto funkcionalne alate.
Veza s drugim modernim funkcijama JavaScripta
Funkcije strelica se rijetko koriste izolovano; gotovo uvijek idu ruku pod ruku s drugim funkcijama Moderni ECMAScript što također utiče na način na koji organizirate i razumijete kod. Neki od najpovezanijih su pustiti y const, u nepromenljivost, el destrukturiranje I to proširena sintaksa.
Poznavanje njihovog pravilnog kombinovanja omogućava vam da pišete vrlo koncizne funkcije strelica koje transformišu podatke pomoću metoda niza kao što su karta, Filter y Smanjitiuvijek održavajući originalno stanje netaknutim, nešto ključno u okruženjima poput Reacta gdje je obrazac nepromjenjivosti norma.
let, const i nepromjenjivost
Dolazak pustiti y const Omogućavao je rad s blokovskim opsezima i referencama koje nisu preraspoređene. U kombinaciji sa streličkim funkcijama, danas je uobičajena praksa deklarisati funkcije kao const mojaFunkcija = () => {…}, osiguravajući da varijabla koja sadrži funkciju neće biti prepisana.
U strukturama podataka kao što su nizovi i objekti, nepromjenjivost se potiče korištenjem Zamrzavanje objekta kada želite izbjeći duboke promjene, te putem operacija širenja i čistih metoda kada trebate kreirati izmijenjene kopije umjesto mijenjanja originala, nešto posebno važno kada renderiranje ili stanje zavisi od otkrivanja promjena.
Literali predložaka, ternarni elementi i kratki spoj
Prilikom renderiranja povratnih poziva, na primjer u JSX-u ili prilikom konstruiranja HTML stringova, gotovo je neizbježno miješati funkcije strelica sa literali šablona (povratne aluzije) i operatori kao što su ternarni ili procjena kratkog spojaOvi operatori vam omogućavaju da napišete vrlo ekspresivne inline uslove koji se odlično uklapaju u deklarativni stil funkcija strelica.
Unutar literala šablona, izrazi ${…} Rješavaju se istim leksičkim opsegom koji dominira `this` funkcija strelica, tako da je bitno biti jasan o tome koje varijable i koji kontekst se koriste u svakoj interpolaciji kako bi se izbjeglo dvosmisleno ponašanje.
Funkcije strelica u iteracijama i kolekcijama
Jedno od područja gdje su funkcije strelica napravile najveću razliku je u obradi nizovi i kolekcijeProsljeđivanje kratkih povratnih poziva metodama poput karta, Filter, pronaći o Smanjiti Postaje mnogo čitljivije sa sintaksom strelica.
Na primjer, filtriranje unosa na listi na osnovu kategorije ili transformiranje API rezultata u interne strukture podataka postaje mnogo deklarativnije i u kombinaciji sa destrukturiranje Lako je izdvojiti samo svojstva koja su vam potrebna iz parametara funkcije.
mapiraj, filtriraj, smanji i kompajliraj
Tipična kombinacija je obično nešto poput ove: lista.filter(item => uslov).map(item => transformacija)povezivanje nekoliko funkcija strelica u metode niza. Svaka od njih nasljeđuje `this` iz konteksta u kojem je definirana, iako se u većini ovih slučajeva `this` čak ni ne koristi, već eksplicitni parametri, što pojačava funkcionalni stil.
En SmanjitiU ovom slučaju, gdje upravljate akumulatorom koji prelazi iz iteracije u iteraciju, streličke funkcije vam omogućavaju da vrlo sažeto izrazite operaciju redukcije, iako je preporučljivo ne pretjerivati s previše gustim izrazima ako želite da kod ostane razumljiv drugim programerima.
Uvoz, izvoz i moduli
U modernom JavaScript ekosistemu, gotovo sav kod je organizovan u modulabilo korištenjem izvorne sintakse uvoz/izvoz ili korištenjem sistema za grupisanje koji se kompajliraju u taj format. U ovom kontekstu, funkcije strelica se vrlo dobro uklapaju kao jedinice funkcionalnosti koje se mogu ponovo koristiti.
Uobičajeno je vidjeti da se komunalne usluge izvoze kao const mojKorisnik = (…) => {…} a zatim uvezeni u različite datoteke. Budući da je svaki modul u svom vlastitom opsegu, ovaj leksikon Kontekst funkcija strelica obično je kontekst modula, što u većini čistih uslužnih programa nije ni relevantno, jer im kontekst nije potreban.
Najbolje prakse s vanjskim modulima i skriptama
Prilikom posluživanja JavaScripta na HTML stranici, poželjno je učitati ga pomoću vanjske datoteke i izbjegavajte ugrađivanje velikih inline blokova. Također, koristite atribut tip="modul" u oznaci skripte omogućava modernu sintaksu uvoz/izvoz i jasno daje do znanja da se datoteka izvršava u režimu strogo default.
Što se tiče performansi, postavljanje skripti modula u glava con odložiti omogućava pregledniku da preuzme i izvrši kod bez blokiranja renderiranja HTML-a, uz održavanje dobrog korisničkog iskustva. U cijeloj ovoj shemi, funkcije strelica su jednostavno najprirodniji način za definiranje malih dijelova logike za višekratnu upotrebu.
Umetanje i manipulisanje DOM-om pomoću modernog JavaScripta
Iako je fokus ove teme na strelici i njenim funkcijama, nemoguće je zanemariti ulogu JavaScripta u Manipulacija DOM-omMetode kao što su getElementById, querySelector, setAttribute ili modifikacija stil Oni su i dalje osnovni, ali danas se obično kombinuju sa povratnim pozivima strelica kako bi reagovali na događaje i ažurirali interfejs.
Rad sa slušaoci događaja koristeći element.addEventListener('click', e => {...}) Ovo je standardni način povezivanja logike s korisničkim interakcijama. U ovim rukovateljima, ovo Unutar funkcije strelice, neće biti DOM element, već vanjski kontekst, tako da ako vam je potreban čvor, morat ćete koristiti sam parametar događaja. e.currentTarget o e.target, umjesto oslanjanja na ovo kao kod starih inline atributa.
Sinhroni JavaScript, asinhroni JavaScript i povratne funkcije
Još jedno važno područje gdje funkcije strelica prave razliku je u asinhrono programiranjeJavaScript je jednonitni i, kako bi se izbjeglo blokiranje interfejsa, delegira spore operacije na preglednik ili Node API-je koji zatim pozivaju vaše povratne funkcije kada završe.
Proslijedi funkcije strelica kao povratne pozive za setTimeout, obećavaHTTP zahtjevi ili pristupi disku čine kod kompaktnijim i održavaju kontekst bez dodatnih trikova. U koraku ugniježđenih povratnih poziva prema obećanja a kasnije prema async/awaitFunkcije strelica su bile ključni element u omogućavanju čitljivosti toka podataka.
Sveukupno, razumijevanje kako Funkcije strelica ovo leksički hvatajuZnati kada su vam one najbolji saveznik, a kada je najbolje nastaviti se oslanjati na tradicionalne funkcije, zajedno sa znanjem kako ih kombinovati sa modulima, metodama nizova, nepromjenjivošću, klasama i petljom događaja, omogućava vam da napišete zaista solidan JavaScript i React; na kraju krajeva, radi se o odabiru pravog oblika funkcije za svaki kontekst, iskorištavajući njene sintaktičke prednosti bez upadanja u granične slučajeve gdje bi njeno `ovo` ponašanje moglo imati kontraefekt. Podijelite ovaj vodič za programiranje i JavaScript funkcije strelica.