Pokud už nějakou dobu programujete v JavaScriptu, jistě jste slyšeli o... funkce šipek a slavné zvláštní chování tentoA je také docela pravděpodobné, že vám hlava už několikrát explodovala, když jste se snažili pochopit proč. tento Pro normální funkci platí jedna věc a pro šipkovou funkci úplně jiná.
Zvládnutí těchto dvou konceptů není jen otázkou teorie: je klíčem k psaní Moderní kód v JavaScriptu a ReactuPochopení fungování obslužných rutin událostí, chování kontextu v rámci tříd, řešení asynchronních zpětných volání v Node.js a proč jsou určité vzory dnes považovány za osvědčené postupy.
Nejprve: rychlý přehled funkcí v JavaScriptu
V JavaScriptu můžete deklarovat funkce několika způsoby a každý způsob má důsledky pro jejich chování. tento, V rozsah a v tuto chvíli je funkce v kódu k dispozici.
Deklarace funkce
Klasická deklarace funkce používá klíčové slovo funkce a název. Tyto typy funkcí jsou „vyvýšené“ (zvedání) na začátku rozsahu platnosti, kde jsou deklarovány, což umožňuje volání funkce ještě před její definicí v souboru.
Ve funkci deklarované tradičním způsobem je hodnota tento je určeno podle jak Funkce je volána: pokud je volána jako metoda objektu, pokud je použita s nový, pokud je v striktním režimu, pokud se přepne do volání, aplikovat o vážouatd. Tato flexibilita je sice silná, ale zároveň je zdrojem mnoha chyb ve složitém kódu.
Výraz funkce
Můžete také přiřadit anonymní nebo pojmenovanou roli proměnlivýV takovém případě se samotná funkce nevyvolá, vyvolá se pouze deklarace proměnné (s byl), ale ne jeho hodnotu. S nechat y const Nemůžete ho použít ani před jeho definiční čárou kvůli dočasná mrtvá zóna.
Tyto funkce sdílejí stejný model tato dynamika Na rozdíl od klasických deklarací: jejich hodnota vždy závisí na kontextu volání, takže zůstávají citlivé na to, jak je předáváte jako callback nebo jak je používáte v rámci tříd a objektů.
Co přesně jsou šipkové funkce?
Funkce se šipkami byly zavedeny pomocí ECMAScript 2015 (ES6) jako pohodlnější, kompaktnější a expresivnější způsob deklarace funkcí, zejména pro zpětná volání a funkcionální programování s metodami jako mapa, filtr o snížit.
Jeho základní syntaxe se skládá ze seznamu parametrů, následovaného operátorem => a pak jeden výraz nebo blok kóduDíky tomuto kompaktnímu formátu je kód efektivnější. čitelný v mnoha scénářích, kde jste dříve museli psát dlouhé a opakující se anonymní funkce.
Základní syntaxe šipkových funkcí
Šipkové funkce podporují několik syntaktických variant, všechny založené na stejných pravidlech, ale se zkratkami pro jednodušší případy. Pochopení každého tvaru vám pomůže lépe psát. čistší kód Rychle rozpoznal, co každé zpětné volání dělá.
- Bez parametrůPřed šipkou se používají prázdné závorky a za nimi obvykle výraz.
const getMessage = () => "Hola"; - Jeden parametrZávorky kolem názvu parametru můžete vynechat, což kód zpřehlední.
const square = x => x * x; - Několik parametrůVždy je nutné použít závorky, které je uzavírají a oddělují čárkami.
const sum = (a, b) => a + b; - Tělo jednoho výrazuPokud nepoužijete složené závorky, výraz se vrátí určitým způsobem. implicitní bez nutnosti psaní zpáteční.
- Víceřádkové těloPokud používáte složené závorky, musíte napsat zpáteční explicitně vrátit hodnotu, stejně jako v normální funkci.
Častým zdrojem chyb je zapomínání zpáteční Když přejdete z jednořádkové verze na tělo se složenými závorkami, abyste přidali více logiky, vaše funkce najednou začne vracet nedefinované A není jasné proč.
Funkce šipek a literální objekty
Pokud funkce s jedním výrazem a šipkou vrátí doslovný objektMusíte ten objekt uzavřít do závorek, aby si ho engine nespletl se začátkem funkčního bloku. Je to malá syntaktická past, která spoustu lidí zaskočí.
Jinak interpret interpretuje klíče jako prázdný blok a vaše funkce nevrátí objekt, ale nedefinovanéTo způsobuje těžko sledovatelné chyby při pokusu o přístup k vlastnostem, které nebyly nikdy vráceny.
Funkce šipek a jejich chování
Skutečným rozlišovacím faktorem šipkových funkcí není syntaxe, ale jejich model tohotoZatímco tradiční funkce mají tato dynamika V závislosti na jejich názvech mají šipkové funkce tento lexikonTedy, zachycují To je z oblasti, ve které byly vytvořeny a ponechávají to beze změny.
To znamená, že v rámci šipkové funkce, tento Nelze to změnit pomocí volání, aplikovat ni vážouA nezáleží na tom, zda ji použijete jako callback v obslužné rutině události, nebo ji předáte jiné funkci. Vždy bude mít stejnou hodnotu, jakou měla mimo ni v době své definice.
Jak to funguje v běžných funkcích?
Ve funkci deklarované s funkce, hodnota tento Záleží na kontextu:
- Pokud funkci zavoláte jako metoda objektu, tento Ukažte na ten objekt.
- Pokud jej vyvoláte bez kontextu v nestriktním režimu, tento odkaz na globální objekt (okno v prohlížeči, globální v Node.js).
- Pokud používáte nový, tento pak ukazuje na nově vytvořená instance.
- Pokud se přihlásíte volání, aplikovat o vážou, můžete vynutit hodnotu tento ručně k objektu dle vašeho výběru.
V striktním režimu, pokud voláte normální funkci bez objektu jako příjemce a bez použití volání nebo podobné, tento bude nedefinovanéProto v mnoha moderních příkladech vidíte funkce, které začínají na 'use strict' aby se předešlo tichým chybám a vynutilo se konzistentnější chování.
Jak to funguje ve funkcích šipek?
V případě šipkových funkcí, tento Při vyvolání se nepřepočítává; je převzato přímo z oblast, kde byly definoványTo znamená, že se chovají podobně, jako když jsou proměnné zachyceny uzávěrem (uzavření): Dívají se ven a tuto hodnotu si pamatují navždy.
To má několik velmi důležitých důsledků pro váš každodenní život:
- Nemůžete použít funkci se šipkami jako konstruktérem s novýprotože nemají své vlastní tento ani vhodný prototyp.
- Volání funkce se šipkou pomocí volání o aplikovat nezmění hodnotu tentoZbytek argumentů však budete moci předat normálně.
- V metodách objektů vytvořených jako šipkové funkce, tento Nebude ukazovat na objekt, ale na horní prostředí (například okno nebo modul), což je téměř vždy chyba.
Klíčovým poznatkem je, že šipkové funkce jsou ideální, když chcete, aby Tento vnitřní je stejný jako ten vnější.Ale jsou špatný nápad, když potřebujete metoda reálných objektů nebo když chcete vytvořit instanci něčeho pomocí nový.
Funkce, třídy a React se šipkami

Ve světě REACT a obecně tříd JavaScriptu, zpracování tento Je to citlivá záležitost. Komponenty třídy zděděné z React.Component Používají metody, ve kterých tento musí konzistentně ukazovat na instanci komponenty, aby bylo možné přistupovat this.props y tento.stát.
S metodami definovanými pomocí klasické syntaxe tříd, hodnota tento Může se „ztratit“ při předávání metody jako zpětného volání události, například onclickProto v mnoha starších tutoriálech uvidíte vzory jako this.metodo.bind(this) v konstruktoru nebo přímo v JSX, což je v dnešní době považováno za poměrně upovídané.
Typické vzorce vazby v Reactu
V komponentě třídy historicky existovaly čtyři hlavní způsoby, jak zajistit, aby tento vždy odkazuje na komponentu, když je volána z obslužné rutiny události:
- Usar vážou v metodě výnos, což zajišťuje kontext, ale při každém vykreslení vytváří novou funkci.
- Udělat vazba v konstruktoru aby se zabránilo opakovanému vytváření funkce, zachování jediné reference.
- Definujte obslužnou rutinu jako vlastnost třídy s funkcí šipky, s využitím skutečnosti, že šipkové funkce zachycují tento instance.
- Použití Funkce šipky inline v JSX, přímé předání funkce šipky atributu onclick nebo ekvivalent.
V praxi je možnost deklarovat obslužnou rutinu jako vlastnost třídy pomocí funkce šipky Stal se z toho nejpohodlnější vzorec: píšete méně kódu, nemusíte dělat vážou manuální a tento vždy se zaměřte na komponentu bez překvapení.
Funkce šipek v komponentách funkcí
S příchodem funkční komponenty a háčkyReact se mnohem více spoléhá na šipkové funkce. Většina moderních komponent je implementována jako šipky. const MojeKomponenta = () => { … }Díky tomu je použití šipkových funkcí přirozené a konzistentní v celém stromu.
V rámci těchto komponent je běžné kombinovat funkce šipek s dalšími funkcemi ES6, jako například ničení, šablonové literály, ternární operátory, rozšířit a metody pole jako mapa, filtr y snížit, čímž se vytváří velmi expresivní syntax, která však vyžaduje dobrou práci s kontextem a neměnnost.
V globálním kontextu, jednotlivé objekty a funkce
Abychom pochopili, proč funkce šipek tolik mění hru, stojí za to se podívat na to, jak se chovají. tento v různých nativních kontextech JavaScriptu, a to jak v prohlížeči, tak v Node.js.
V globální rozsah prohlížeče, mimo jakoukoli funkci nebo modul, tento ukažte na objekt oknoTo znamená, že jakákoli proměnná deklarovaná pomocí byl Na vyšší úrovni visí na tomto globálním objektu a je přístupný jak podle jména, tak i podle název_oknaTo je v komplexních aplikacích považováno za špatný postup kvůli globálnímu znečištění.
toto v rámci doslovných objektů
Když definujete doslovný objekt U tradičních metod každá metoda dostává tento který odkazuje na samotný objekt při jeho volání jako obj.method()Toto je standardní způsob přístupu k sesterským nemovitostem pomocí tato.vlastnost bez nutnosti mezilehlých proměnných.
Problém nastává, když tyto metody nahradíte funkce šipekProtože nemáme tento vlastníFunkce se šipkou zachytí externí `this`, což je pravděpodobně globální nebo modulární `this`. V důsledku toho nebudete moci přistupovat k vlastnostem objektu v rámci metody pomocí tento, což zcela narušuje původní záměr návrhu.
Toto je v rámci volných funkcí a striktního režimu
V tradičních funkcích nazývaných „unplugged“, bez přijímajícího objektu, hodnota tento Záleží na tom, zda je kód v přísný režim Nebo ne. Přísně vzato, spadá to zpět do globální objekt, i když striktně vzato se explicitně stává nedefinovanéaby se zabránilo nebezpečným akcím pro globální životní prostředí.
Toto chování se drasticky mění, když zapouzdříte kód do ES modulů, moderních bundlerů nebo IIFE, kde se globální proměnná může lišit nebo nemusí být vázána na… tento obvyklým způsobem, zejména v Node.js, kde hlavní oblastí působnosti archivu je modul a ne ten globální.
volání, použití, vazba a jejich vztah k tomuto
JavaScript nabízí oproti klasickým funkcím tři široce používané metody pro správu kontextu: volání, aplikovat y vážouVšechny vám umožňují explicitně kontrolovat, jakou hodnotu nabývá. tento když je funkce provedena.
Tyto metody fungují pouze s funkce deklarované s funkcí function (nebo ekvivalenty), protože šipkové funkce ignorují jakýkoli pokus o změnu jejich `this`. Proto jsou všechny tři tak užitečné při práci se staršími API, starými třídami nebo vzory, kde chcete stejnou funkci znovu použít na různých objektech.
zavolat a použít: vyvolat s explicitním this
tak volání jak aplikovat funkci provedou okamžitěJediný rozdíl je ve způsobu předávání argumentů. V obou případech je prvním předávaným parametrem objekt, který má být převeden. tento v rámci funkce.
s volání Následující argumenty jsou uvedeny jeden po druhém, zatímco u aplikovat Vydávají se za řadaTo se velmi dobře hodí do situací, kdy již máte seznam argumentů jako kolekci a chcete jej vložit do volání tak, jak je.
bind: vytvoření nové funkce s `this` set
Metoda vážou Funkci v danou chvíli neprovede, ale místo toho vygeneruje nová funkce s toto trvale spojené k objektu, který zadáte. Je to jako vytvořit „specializovanou“ verzi originálu, která se bude vždy chovat v daném kontextu.
Tento vzor je velmi běžný pro předávání objektových metod API, která je později volají, například jako zpětná volání událostí, aniž by ztratila původní kontext. Před popularizací šipkových funkcí vážou Byl to jeden z nejčistších způsobů, jak zajistit, aby metoda třídy i nadále ukazovala na správnou instanci.
Proč jsou šipkové funkce ideální pro zpětná volání?
Jedním z důvodů, proč šipkové funkce dobyly ekosystém JavaScriptu, je jejich vhodnost pro asynchronní zpětná volání a funkcionální programování. Při práci s API, jako je setTimeout, setInterval, Slibuje Nebo s cyklem událostí Node.js často potřebujete přistupovat k vnějšímu kontextu, aniž by došlo k jeho zkreslení.
Před ES6 se používaly triky jako ukládání const self = this o konstanta, která = toto před zadáním zpětného volání, aby bylo možné z funkce stále odkazovat na správný objekt. Šipkové funkce to činí zbytečným tím, že automaticky zachytí Tento externí a zachovat to.
Funkce se šipkami a smyčka událostí v Node.js
En Node.js, kolem kterého se točí většina zajímavého kódu Asynchronní vstup/výstup (soubory, síť, časovače), kombinace šipkových funkcí s modelem smyčka událostí a fronty zpětných volání Hodně to zjednodušuje život. Pokaždé, když předáte funkci, jako je handle, fs.readFileAť už odesíláte data na HTTP server nebo na jakoukoli operaci knihovny libuv, šipkové funkce pomáhají udržet odkazy na souvislé proměnné a kontexty modulů bez překvapení.
Dále ve frontách mikroúkolů, jako jsou ty od Slibuje o process.nextTickJe velmi běžné psát krátké zpětné volání jako pak o úlovek se syntaxí šipek, s využitím obou implicitní návrat jak tento lexikon, díky čemuž je kód deklarativnější a expresivnější.
Kdy byste NEMĚLI používat šipkové funkce?
Ačkoli se šipkové funkce mohou jevit jako magické řešení všech problémů, existují scénáře, kdy je jejich použití přímo kontraproduktivní a dokonce generuje chyby, které je obtížné odhalit.
Jedním z nich, možná tím nejdůležitějším, je metody objektů nebo tříd, které potřebují vlastní `this`Další je, když chcete vytvořit stavitelé nebo použít objektově orientované vzory podporované prototypy a dědičností, kde absence prototyp a jeho vlastní kontext znamená, že šipkové funkce prostě nezapadají.
Nepoužívejte šipkové funkce jako objektové metody.
Pokud definujete metodu objektu s funkcí typu šipka, Tato interní vlastnost se nebude odkazovat na objekt.ale spíše kontextu, ve kterém byl daný objekt definován. To narušuje očekávání každého, kdo čte kód a má v úmyslu jej použít tato.vlastnost v rámci metody.
Doporučený způsob psaní metod, které závisí na tento Jde o to pokračovat v používání klasické syntaxe v literálních objektech nebo deklarovat tyto metody standardním způsobem ve třídách a rezervovat šipkové funkce pro interní zpětná volání, která potřebují zachytit tento z nadřazené metody.
Nepoužívejte šipkové funkce jako konstruktory.
Chybí funkce šipek [[Postavit]], vnitřní mechanismus, který umožňuje vyvolání funkce pomocí novýProto pokus o jejich použití jako konstruktorů vygeneruje chybu. Zadejte ChybaAni oni nemají vlastní. prototypProto nelze zablokovat sdílené metody pro instance.
Pokud váš návrh vyžaduje opakovaně použitelné instance se společnými vlastnostmi a metodami, měli byste zvolit clases nebo tradičními konstruktorovými funkcemi, přičemž šipkové funkce zůstávají pro bezstavovou logiku nebo čistě funkční utility.
Vztah s dalšími moderními funkcemi JavaScriptu
Funkce šipek se zřídka používají samostatně; téměř vždy jdou ruku v ruce s dalšími funkcemi Moderní ECMAScript které také ovlivňují, jak organizujete a chápete kód. Mezi nejčastěji související patří nechat y const, neměnnostse ničení a syntaxe šíření.
Znalost správné kombinace těchto funkcí vám umožní psát velmi stručné šipkové funkce, které transformují data pomocí maticových metod, jako například mapa, filtr y snížitvždy zachovat původní stav neporušený, což je v prostředích jako React, kde je vzorec neměnnosti normou, klíčové.
let, const a neměnnost
Příchod nechat y const Umožňovalo to práci s blokovými obory a s referencemi, které nebyly znovu přiřazeny. V kombinaci s šipkovými funkcemi je dnes běžnou praxí deklarovat funkce jako const mojeFunkce = () => {…}, čímž se zajistí, že proměnná obsahující funkci nebude přepsána.
V datových strukturách, jako jsou pole a objekty, je neměnnost podporována použitím Objekt.zmrazení když se chcete vyhnout hlubokým změnám a pomocí operací rozložení a čistých metod, když potřebujete vytvořit upravené kopie Místo změny originálu je důležité něco, co je obzvláště důležité při vykreslování nebo vyhodnocování stavu, a to na detekci změn.
Šablonové literály, ternární algoritmy a zkraty
Při vykreslování zpětných volání, například v JSX nebo při konstrukci HTML řetězců, je téměř nevyhnutelné kombinovat šipkové funkce s šablonové literály (zpětné anotace) a operátory jako například trojice o la vyhodnocení zkratuTyto operátory umožňují psát velmi expresivní inline podmínky, které se velmi dobře hodí k deklarativnímu stylu šipkových funkcí.
V rámci šablonových literálů, výrazy ${…} Jsou řešeny se stejným lexikálním rozsahem, který dominuje funkci `this` šipkových funkcí, takže je nezbytné mít jasno v tom, které proměnné a jaký kontext se v každé interpolaci používají, aby se předešlo nejednoznačnému chování.
Šipkové funkce v iteracích a kolekcích
Jednou z oblastí, kde šipkové funkce přinesly největší rozdíl, je zpracování pole a kolekcePředávání krátkých zpětných volání metodám jako mapa, filtr, nalézt o snížit Díky syntaxi šipek se to stává mnohem čitelnějším.
Například filtrování položek v seznamu na základě kategorie nebo transformace výsledků API do interních datových struktur se stává mnohem deklarativnějším a v kombinaci s ničení Z parametrů funkce je snadné extrahovat pouze ty vlastnosti, které potřebujete.
mapovat, filtrovat, redukovat a spol.
Typická kombinace je obvykle něco takového: seznam.filter(položka => podmínka).map(položka => transformace)řetězení několika šipkových funkcí do metod pole. Každá z nich dědí `this` z kontextu, kde je definována, ačkoli ve většině těchto případů se `this` ani nepoužívá, ale spíše se používají explicitní parametry, což posiluje funkční styl.
En snížitV tomto případě, kdy spravujete akumulátor, který přechází z iterace do iterace, vám šipkové funkce umožňují vyjádřit operaci redukce velmi stručně, i když je vhodné nepoužívat příliš husté výrazy, pokud chcete, aby kód zůstal srozumitelný pro ostatní vývojáře.
Importy, exporty a moduly
V moderním ekosystému JavaScriptu je téměř veškerý kód uspořádán do modulybuď pomocí nativní syntaxe import / export nebo použitím systémů pro sdružování, které se kompilují do tohoto formátu. V tomto kontextu se šipkové funkce velmi dobře hodí jako opakovaně použitelné funkční jednotky.
Je běžné, že se utility vyvážejí jako const myUtil = (…) => {…} a poté importovány do různých souborů. Protože každý modul je ve svém vlastním rozsahu, tento lexikon Kontext šipkových funkcí bývá kontextem modulu, což ve většině čistých utilit ani není relevantní, protože kontext nepotřebují.
Nejlepší postupy s externími moduly a skripty
Při načítání JavaScriptu na HTML stránce je lepší jej načíst pomocí externí soubory a vyhněte se vkládání velkých inline bloků. Použijte také atribut typ="modul" v tagu skriptu umožňuje moderní syntaxi import / export a jasně ukazuje, že soubor je spuštěn v režimu přísné výchozí.
Co se týče výkonu, umístění skriptů modulů do hlava s odložit umožňuje prohlížeči stáhnout a spustit kód bez blokování vykreslování HTML a zároveň zachovat dobrou uživatelskou zkušenost. V celém tomto schématu jsou šipkové funkce jednoduše nejpřirozenějším způsobem, jak definovat malé části opakovaně použitelné logiky.
Vkládání a manipulace s DOM pomocí moderního JavaScriptu
Ačkoli se toto téma zaměřuje na šipku a funkce `this`, nelze ignorovat roli JavaScriptu v Manipulace s DOMemMetody jako například getElementById, querySelector, setAttribute nebo modifikace styl Stále jsou základní, ale dnes se obvykle kombinují s callbacky šipek, aby reagovaly na události a aktualizovaly rozhraní.
Pracovat s posluchače událostí pomocí element.addEventListener('click', e => {...}) Toto je standardní způsob, jak propojit logiku s interakcemi uživatele. V těchto obslužných rutinách tento Uvnitř funkce arrow to nebude prvek DOM, ale externí kontext, takže pokud potřebujete uzel, budete muset použít samotný parametr události. e.currentTarget o e.target, místo spoléhání se na to jako u starých inline atributů.
Synchronní JavaScript, asynchronní JavaScript a zpětná volání
Další důležitou oblastí, kde funkce šipek hrají roli, je asynchronní programováníJavaScript je jednovláknový a aby se zabránilo blokování rozhraní, deleguje pomalé operace na prohlížeč nebo Node API, které po dokončení volají vaše zpětná volání.
Předávat funkce šipek jako zpětná volání do setTimeout, slibyHTTP požadavky nebo přístupy na disk dělají kód kompaktnějším a zachovávají kontext bez dalších triků. V kroku vnořených zpětných volání směrem k Slibuje a později směrem asynchronní/čekatŠipkové funkce byly základním prvkem pro zajištění čitelnosti datového toku.
Celkově vzato, pochopení toho, jak šipkové funkce to lexikálně zachycujíVědět, kdy jsou vaším nejlepším spojencem a kdy je nejlepší se nadále spoléhat na tradiční funkce, spolu se znalostí toho, jak je kombinovat s moduly, metodami polí, neměnností, třídami a smyčkou událostí, vám umožňuje psát skutečně solidní JavaScript a React; v konečném důsledku jde o výběr správného tvaru funkce pro každý kontext a využití jejích syntaktických výhod, aniž by se člověk dostal do hraničních případů, kdy by se jeho chování „toto“ mohlo obrátit proti vám. Sdílejte tuto programátorskou příručku a funkce šipek v JavaScriptu.