Js funkcije strelice. O ključnoj riječi JavaScript “this”: značajke korištenja s objašnjenjima. Pravila za korištenje funkcija strelica

Postali su vrlo moderni, vidimo ih u svim novim člancima. I, ako niste navikli na njih, teško ćete razumjeti moderni (ES6) kod koji sadrži funkcije strelica.

Ovaj članak nema namjeru da vam kaže kada ili kako ih koristiti. Pokušat ću objasniti novu sintaksu za one koji je vide prvi put. Hoćete li ga koristiti ili ne, nije važno, ali prije ili kasnije ćete ga ipak negdje susresti. Stoga je bolje razumjeti mehaniku ove nove sintakse.

Evo malog primjera:

Const addOne = function(n) ( return n + 1; )

Gornji kod može se napisati ovako:

Const addOne = (n) => ( return n + 1; )

Ili unutra u ovom slučaju, još kraće:

Const addOne = (n) => n + 1;

Drugi primjer koristi ( ... ) vitičaste zagrade, ali budući da je to samo jedan redak koda, vitičaste zagrade se mogu izostaviti i povratak se podrazumijeva, kao što se vidi u trećem primjeru.

Jedan parametar

Kada funkcija strelice ima jedan parametar, zagrade se mogu izostaviti:

// Bilo je: someCallBack((rezultati) => ( ... )) // Sada: someCallBack(rezultati => ( ... ))

Ali, ako nema parametara, morate koristiti otvarajuće i zatvarajuće zagrade:

SomeCallBack(() => ( ... ))

Funkcije povratnog poziva

Funkcijske strelice posebno su korisne za povratne pozive. Oni koji su upoznati s JavaScriptom upoznati su s njegovim leksičkim opsegom, koji je prilično uredan, ali može izvesti ovakve trikove ( ovaj):

Var_this = ovo; someCallBack(function() ( _this.accessOuterScope(); ))

Postoji nekoliko varijacija ovog "_this" (kao što su "self" ili "that"), ali ideja je ista. U funkcijama povratnog poziva trebamo pristup verziji vanjskog opsega, ali ideja je ista. U funkcijama povratnog poziva, potreban nam je pristup verziji ovog vanjskog opsega, koja se sada razlikuje od prije jer govorimo o funkciji povratnog poziva.

Pomoću funkcije strelice, dobivamo "opseg bloka" i "ovo", što je isto "ovo" u oba slučaja. To znači da se gornji kod može prepisati bez _this = this:

SomeCallBack(() => ( this.accessOuterScope(); ))

"Omot"

Zamislimo situaciju kao u Reactu, gdje događaj na klik treba pozvati doSomething() , (), ali također treba proslijediti argumente doSomething() (npr. ID). Ovaj primjer zapravo ne radi:

Neki korisnik))

Kod će se pokrenuti, ali tehnički će pozvati doSomething() odmah kada se stranica učita. Kako bi riješili ovaj problem, neki se programeri pozivaju na funkciju omotača:

Const User = React.createClass(function() ( render: function() ( return Some user), onClick: function() ( doSomething(this.props.userId); ) ))

Nepostojanje zagrada u this.onClick znači da je to jednostavno referenca funkcije, a ne poziv funkcije.

Funkcija onClick() sada je nešto poput omotača za doSomething(). Pomoću funkcija strelica možete napraviti "omotače" ove vrste:

Const User = React.createClass(function() ( render: function() ( return doSomething(this.props.userId))>Some user ) ))

Kao alternativu, također bismo mogli koristiti .bind(), koji ne zahtijeva nikakve omote (funkcije strelica ili bilo što):

Const User = React.createClass(function() ( render: function() ( return Some user ) ))

Podrška preglednika za funkcije strelica

Ako trebate podršku preglednika osim najnovije verzije Krom I Firefox, koristiti Babel transpiler da pretvorite ES6 kod koji ste napisali u ES5.

ES6 ima novi način stvaranja funkcija - korištenjem strelice => operatora. Takve funkcije nazivamo streličastim funkcijama. Oni nude kompaktniju sintaksu. Oni nemaju ime i rade drugačije s ovim.

Prvo što ćemo učiniti je pokrenuti Babel skriptu koja će nadzirati datoteke i stvarati nove verzije kada se promijene.

Otvorite mapu projekta u naredbeni redak(KS). Unesite naredbu:

I pritisnite Enter

U mapi src kreirat ćemo datoteku arr.js i odmah je naznačiti u datoteci index.html

</skripta>

Najnovije verzije preglednika podržavaju funkcije strelica bez transpilacije, a moj preglednik je jedan od njih.

Napišimo funkciju koja zbraja dva broja i vraća njihov zbroj. Nazovimo funkciju add.

Funkcija add (x, y) ( return x + y; ) console.log (add (3, 6));

Na konzoli ćemo vidjeti rezultat - 9

Sada, pretvorimo ovu funkciju u funkciju strelice.

Uklonimo riječ funkcija , uklonimo naziv funkcije i uklonimo vitičaste zagrade, te riječ - return . Nakon parametara stavit ćemo strelicu.

Neka se zbroji = (x, y) => x + y; console.log(add(4, 6));

Ako pogledate vrstu varijable add pomoću operatora typeof:

Console.log(typeof(add));

To je ono što ćemo vidjeti u funkcijskoj konzoli

To znači da su funkcije strelica obične funkcije. I to možete provjeriti gledajući transpilirani kod.

"koristi strog"; var _typeof = typeof Symbol === "funkcija" && typeof Symbol.iterator === "symbol" ? funkcija (obj) ( return typeof obj; ) : funkcija (obj) ( return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj ; ); var add = funkcija add(x, y) ( return x + y; ); console.log(add(4, 6)); console.log(typeof add === "undefined" ? "undefined" : _typeof(add));

Vidimo da je Babel pretvorio naš kod u jednostavan funkcijski izraz.

Napišimo jednostavnu funkciju koja će kvadrirati zadani broj.

Neka se zbroji = (x, y) => x + y; console.log(add(4, 6)); console.log(typeof(add)); neka square = function(a) ( return a * a; ) console.log(square (4));

Pogledajmo u konzoli:

Funkcija strelice izgledat će ovako:

Neka je kvadrat = x => x * x;

Ako funkcija strelice uzima samo jedan parametar, nema potrebe stavljati ga u zagrade!

Napišimo funkciju koja ne uzima nikakve parametre.

Funkcija givNumer () ( return 33; ) console.log(givNumer ());

Ova funkcija jednostavno ispisuje broj 33 na konzolu:

Neka je givBroj = () => 33; console.log(givNumer());

Kreirajmo funkciju koja neće ništa vraćati. Jednostavno će prikazati poruku u konzoli preglednika.

Neka log = funkcija () ( console.log("Hello World!"); ); log();

Sklopka:

Neka log = () => console.log("Hello World!!!"); log();

Kreirajmo funkciju čije će se tijelo sastojati od dvije linije.

Funkcija će uzeti dva parametra. Kreirajmo varijablu u tijelu funkcije. Nakon toga ćemo vratiti rezultat.

Neka je mult = funkcija (a, b) ( neka rezultat = a * b; vrati rezultat; ) console.log(mult (4, 5));

Ako postoji nekoliko redaka u funkciji strelice, tada su potrebne vitičaste zagrade - ()! I svakako definirajte što ova funkcija vraća pomoću ključne riječi return

Sklopka:

Neka mult = (a, b) => ( neka rezultat = a * b; vrati rezultat; ) console.log(mult (4, 5));

Kreirajmo sada funkciju koja vraća literal objekta:

Neka literal = funkcija () ( return ( ime: "John"); ) console.log (literal ());

U konzoli ćemo vidjeti:

Pokušajmo sada stvoriti funkciju strelice koja će vratiti literal objekta.

Treba imati na umu da ako funkcija strelica vraća literal objekta, tada su potrebne zagrade - ()

Funkcija strelice koja vraća literal objekta:

Neka literal = () => ((ime: "John")); konzola.log(literal());

Pokušajmo sada upotrijebiti funkciju strelice kao izraz IIFE - funkcije koja se odmah poziva

Ukratko, ovo je funkcija koja se izvršava odmah nakon deklaracije

Ovako izgleda:

(funkcija () ( console.log("IIFE"); ))();

Funkcija strelice IIFE izgledat će ovako:

(() => console.log("IIFE"))();

Važna značajka funkcija strelica je da strelica mora doći odmah nakon parametara!

Ne možete ga jednostavno uzeti i premjestiti u redak ispod. Dat će pogrešku!

Praktična primjena funkcija strelice. Funkcije strelica vrlo su prikladne za korištenje s nizovima.

Kreirajmo niz s nekim brojevima i nazovimo ga brojevi. Mislim da znate da nizovi imaju korisne metode koje vam omogućuju ponavljanje kroz niz, filtriranje itd.

Izračunajmo zbroj svih varijabli niza. Da bih to učinio, deklarirat ću drugu varijablu - neka je suma = 0;

Upotrijebimo metodu forEach() koju ima svaki niz, iterirati ćemo po elementima i dodati zbroju.

Neka su brojevi = ; neka je zbroj = 0; numbers.forEach(function(num) ( sum += num; )); konzola.log(zbroj);

Na konzoli ćemo vidjeti 55. Pretvorimo ovu funkciju u funkciju strelice: numbers.forEach(num => sum += num); konzola.log(zbroj);

Dakle, ono za što su nam prije bila potrebna tri reda sada ima jedan.

Također možemo kvadrirati svaki element niza.

Neka je na kvadrat = numbers.map(n => n * n); console.log(na kvadrat);

Funkcije strelice i ovo . Da bih to učinio, stvorit ću literal objekta koji ću spremiti u varijablu osoba.

Objekt osobe imat će svojstvo name s vrijednošću 'Bob' i svojstvo greet s vrijednošću 'Greet'. Ispisat ćemo pozdrav na konzoli i također pogledati svrhu ovoga.

Let person = ( name: "Bob", greet: function () ( console.log("Zdravo! Moje ime je " + this.name); console.log(this); ) ); person.greet();

U konzoli preglednika vidjet ćemo pozdrav i sam objekt osobe.

Sada ćemo funkciju zamijeniti strelicom i vidjeti što će se dogoditi s ovim.

Let person = ( name: "Bob", greet: () => ( console.log("Zdravo! Moje ime je " + this.name); console.log(this); ) ); person.greet();

Sada nismo dobili vrijednost imena i vrijednost ovoga je prozor!

Ali zašto? Poanta je da je vrijednost ovoga uzeta iz konteksta u kojem je funkcija deklarirana. ! Bez obzira gdje će se ova funkcija obavljati. To se može vidjeti na slici:

Imamo program.

Za sada u njemu nema ničega osim objekta prozora. Dodan je objekt osobe. Primijetite da za metodu koristimo funkciju strelice. Kao što smo rekli, vrijednost ovoga bit će uzeta iz konteksta. Kontekst je okruženje. U ovom slučaju bit će okruženje objekta osobe, sva njegova svojstva i metode objekt prozora. A ako se vrijednost ovoga uzme iz konteksta, onda će se ovo odnositi na objekt prozora.

Ako pogledamo regularnu funkciju, onda znamo da se to odnosi na sam objekt osobe. Možete pitati zašto je vrijednost ovog u funkcijama strelica uzeta iz konteksta? A odgovor je vrlo jednostavan – tako su i napravili! :-) Stvar je u tome da su funkcije strelica stvorene za rješavanje problema u različitim situacijama. Pogledajmo primjer. Da vidimo problem vratit ćemo se na našu funkciju strelice.

Let person = ( name: "Bob", greet: function () ( console.log("Zdravo! Moje ime je " + this.name); console.log(this); ) );

Zamislimo da je naš Bob prilično zaposlen i treba mu nekoliko sekundi da dovrši svoj posao. Pričekajte 2 sekunde. simuliramo pomoću funkcije setTimeout(); .Ova funkcija uzima funkciju kao prvi parametar i broj milisekundi čekanja kao drugi parametar.

Let person = ( name: "Bob", greet: function () ( setTimeout(function () ( console.log("Zdravo! Moje ime je " + this.name); console.log(this); ), 2000) ; ) ); person.greet();

Ako imate iskustva s JavaScriptom, mislim da razumijete u čemu je problem. U svakom slučaju, pogledajmo što će se dogoditi u pregledniku. Točno dvije sekunde kasnije vidjet ćemo ovu sliku u pregledniku.

Ali zašto? Ako pogledate naš kod, logično je pretpostaviti. da se ovo odnosi na objekt osobe budući da koristimo regularnu funkciju. Stvar je u tome što setTimeout() pripada objektu prozora. Ako to napišete ovako: window.setTimeout() , što mislite na što se onda odnosi? I u konzoli ćemo dobiti isti rezultat! Postoji nekoliko načina za rješavanje ovog problema u ES5. Pogledat ćemo najčešći: Prije setTimeout(), deklarirat ću drugu varijablu koja će joj biti dodijeljena kao vrijednost. A sada, u tijelu funkcije, umjesto ovoga, označit ćemo ono.

Let person = ( name: "Bob", greet: function () ( let that = this; setTimeout(function () ( console.log("Zdravo! Moje ime je " + that.name); console.log(that) ; ), 2000. ) ); person.greet();

Sada, zahvaljujući zatvaranju, funkcija koju šaljemo setTimeout() imat će pristup varijabli that, čija će vrijednost biti this , to jest, u ovom slučaju, objekt osobe.

Radi jasnoće, možete pogledati na što se odnosi ono i ovo.

Let person = ( name: "Bob", greet: function () ( let that = this; setTimeout(function () ( console.log("Zdravo! Moje ime je " + that.name); console.log("To je moje Ono = " + ono); console.log("To je moje Ovo = " + ovo); ), 2000); ) ); person.greet();

Vidjet ćemo potvrdu na konzoli:

Vidimo da će ovo biti objekt prozor - This = , a to će biti naš objekt person - That = .

U ES6, možemo jednostavno koristiti funkciju strelice da riješimo ovaj problem.

Let person = ( name: "Bob", greet: function () ( setTimeout(() => ( console.log("Zdravo! Moje ime je " + this.name); console.log("To je moj Ovo = " + ovo); ), 2000); ) ); person.greet();

Kao rezultat toga, vidjet ćemo na konzoli:

U grafički primjer za funkciju strelice, kontekst će biti objekt osobe, a ne objekt prozora. zato će se ovo odnositi na osobu .

Uz kompaktnu sintaksu, uvedene su funkcije strelica za rješavanje problema poput ovih.

Za referencu, možete vidjeti kako je Babel ovo riješio

Var person = ( name: "Bob", greet: function greet() ( var _this = this; setTimeout(function () ( console.log("Zdravo! Moje ime je " + _this.name); console.log(" To je moj Ovo = " + _ovo); ), 2000); ) ); person.greet(); Babel je koristio istu metodu koju smo koristili u ES5. Jedina je razlika što smo mi varijablu nazvali tako, a Babel ju je nazvao - _ovo. Zahvaljujući zatvaranju, funkcija koju šaljemo setTimeoutu imat će pristup varijabli _this i, kao rezultat toga, objektu osobe.

Mislim da je najteži dio ovog dijela razumjeti kako funkcioniraju zatvaranja.

Još neke značajke funkcija strelica:
Više informacija o ES6 i funkcijama strelica možete vidjeti u mom postu

Bok svima! U ovom članku ćemo pogledati koje su funkcije strelica u ES6 i kako ih koristiti.

Funkcije strelica su funkcije koje se pišu pomoću operatora strelice (=>).

Pogledajmo odmah primjer:

Neka se zbroji = (x, y) => x + y;
console.log(add(5, 2));

Kao rezultat izvršavanja ove funkcije, vidjet ćemo broj 7 na konzoli.

Prvo proslijeđujemo argumente u zagradama, zatim stavljamo znak strelice, a zatim pišemo kod same funkcije. U našem slučaju, jednostavno uzima dva broja i zbraja ih. U teoriji, ovo je isto kao izraz funkcije u ES5. Ako koristite Babel ili slične prevoditelje, oni će najvjerojatnije napisati nešto poput ovoga:

Var add = funkcija add(x, y) (
povratak x + y;
};

Ako vaša funkcija uzima samo jedan parametar, zagrade nisu obavezne.

Neka je kvadrat = x => x*x;

Ova funkcija uzima samo jedan argument i kvadrira zadani broj.

Funkcija bez parametara:

Neka je func = () => 77;

Ako vaša funkcija sadrži nekoliko redaka, prvo morate koristiti vitičaste zagrade, a drugo, obavezno napišite što funkcija vraća, tj. koristite ključnu riječ return.

Neka množimo = (x, y) => (
neka rezultat = x*y;
vratiti rezultat;
};

Ako trebate vratiti literal objekta, tada ga trebate zamotati u zagrade:

Neka getObject = () => (( brand: "BMW" ));

Funkcija samopozivanja izgleda ovako:

Izraz funkcije strelice sintaktički je kompaktna alternativa izrazu regularne funkcije, iako bez vlastitih veza s ključnim riječima this, arguments, super ili new.target. Izrazi funkcije strelice nisu prikladni kao metode i ne mogu se koristiti kao konstruktori.

Sintaksa Osnovna sintaksa (param1, param2, …, paramN) => ( izjave ) (param1, param2, …, paramN) => izraz // ekvivalentno: => ( povratni izraz; ) // Zagrade su izborne kada postoje samo jedan naziv parametra: (singleParam) => ( izjave ) singleParam => ( izjave ) // Popis parametara za funkciju bez parametara treba biti napisan s parom zagrada () => ( izjave ) Napredna sintaksa // Zagrada tijelo funkcije za vraćanje literalnog izraza objekta: params => ((foo: bar)) // Podržani su parametri Rest i zadani parametri (param1, param2, ...rest) => ( izjave ) (param1 = defaultValue1 , param2, …, paramN = defaultValueN) => ( izjave ) // Destrukturiranje unutar popisa parametara također je podržano var f = ( = , (x: c) = (x: a + b)) => a + b + c; f(); // 6 Opis

Dva su čimbenika utjecala na uvođenje funkcija strelica: potreba za kraćim funkcijama i ponašanje ključne riječi this.

Kraće funkcije var elements = [ "Hidrogen", "Helij", "Litij", "Berilij" ]; // Ova izjava vraća niz: elements.map (function(element) ( return element.length; )); // Redovna funkcija iznad može se napisati kao funkcija strelice ispod elements.map((element) => ( return element.length; )); // // Kada postoji samo jedan parametar, možemo ukloniti okolne zagrade elements.map (element => ( return element.length; )); // // Kada je jedina izjava u funkciji strelice `return`, možemo ukloniti `return` i ukloniti // okolne vitičaste zagrade elements.map(element => element.length); // // U ovom slučaju, budući da nam treba samo svojstvo duljine, možemo koristiti parametar destrukturiranja: // Primijetite da `length` odgovara svojstvu koje želimo dobiti, dok je // očito nespecijalno `lengthFooBArX` samo ime varijable koje se može promijeniti // u bilo koje važeće ime varijable koju želite elements.map ((( length:lengthFooBArX )) => lengthFooBArX); // // Ova dodjela parametra destrukturiranja također se može napisati kao što je prikazano u nastavku. Međutim, imajte na umu da u // ovom primjeru ne dodjeljujemo vrijednost `length` izmišljenom svojstvu. Umjesto toga, samo doslovno ime // varijable `length` koristi se kao svojstvo koje želimo dohvatiti iz objekta. elementi.map ((( duljina )) => duljina); // Ovo nije odvojeno

Prije funkcija strelica, svaka je nova funkcija definirala vlastitu ovu vrijednost na temelju načina na koji je funkcija pozvana:

  • Novi objekt u slučaju konstruktora.
  • nedefinirano u pozivima funkcija strogog načina.
  • Osnovni objekt ako je funkcija pozvana kao "metoda objekta".

To se pokazalo manje nego idealnim s objektno orijentiranim stilom programiranja.

Function Person() ( // Konstruktor Person() definira `this` kao instancu samog sebe. this.age = 0; setInterval(function growUp() ( // U nestriktnom načinu rada, growUp() funkcija definira ` this` // kao globalni objekt (jer je to mjesto gdje se growUp() izvršava.), // koji se razlikuje od `this` // definiranog konstruktorom Person(). this.age++; ), 1000) ; ) var p = nova osoba();

U ECMAScriptu 3/5 ovaj se problem mogao popraviti dodjeljivanjem vrijednosti u ovome varijabli koja se može zatvoriti.

Function Person() ( var that = this; that.age = 0; setInterval(function growUp() ( // Povratni poziv odnosi se na varijablu `that` čija je // vrijednost očekivani objekt. that.age++; ) , 1000) "koristi striktno"; var obj = (a: 10); Object.defineProperty(obj, "b", ( get: () => ( console.log(this.a, typeof this.a, this); // undefined "undefined" Window (...) (ili globalni object) return this.a + 10; // predstavlja globalni objekt "Window", stoga "this.a" vraća "undefined" ) ));

Korištenje novog operatora

Funkcije strelica ne mogu se koristiti kao konstruktori i izbacit će pogrešku kada se koriste s new .

Var Foo = () => (); var foo = new Foo(); // TypeError: Foo nije konstruktor

Korištenje svojstva prototipa

Funkcije strelica nemaju svojstvo prototipa.

Var Foo = () => (); konzola.log(Foo.prototip); //nedefiniran

Upotreba ključne riječi yield

Ključna riječ yield ne smije se koristiti u tijelu funkcije strelice (osim kada je dopušteno unutar funkcija koje su dodatno ugniježđene unutar nje). Kao posljedica toga, funkcije strelice ne mogu se koristiti kao generatori.

Funkcijsko tijelo

Funkcije strelica mogu imati "koncizno tijelo" ili uobičajeno "blok tijelo".

U sažetom tijelu specificiran je samo izraz koji postaje implicitna povratna vrijednost. U tijelu bloka morate koristiti eksplicitnu povratnu naredbu.

Var func = x => x * x; // koncizna sintaksa tijela, implicirano "povratak" var func = (x, y) => ( return x + y; ); // s tijelom bloka, potreban eksplicitan "return".

Vraćanje literala objekta

Imajte na umu da vraćanje literala objekta pomoću konciznih parametara sintakse tijela => (objekt:literal) neće raditi kako se očekuje.

Var func = () => ( foo: 1 ); // Pozivanje func() vraća nedefinirano! var func = () => ( foo: funkcija() () ); // SyntaxError: izjava funkcije zahtijeva naziv

To je zato što se kod unutar vitičastih zagrada (()) analizira kao slijed iskaza (tj. foo se tretira kao oznaka, a ne kao ključ u literalu objekta).

Morate staviti literal objekta u zagrade:

Var func = () => (( foo: 1 ));

Prekidi redaka

Funkcija strelice ne može sadržavati prijelom retka između svojih parametara i strelice.

Var func = (a, b, c) => 1; // SyntaxError: očekivani izraz, dobio "=>"

Međutim, ovo se može izmijeniti stavljanjem prijeloma retka nakon strelice ili korištenjem zagrada/zagrada kao što se vidi u nastavku kako bi se osiguralo da kod ostane lijep i lepršav. Također možete staviti prijelom retka između argumenata.

Var func = (a, b, c) => 1; var func = (a, b, c) => (1); var func = (a, b, c) => ( return 1 ); var func = (a, b, c) => 1; // sintaksna pogreška nije izbačena

Redoslijed raščlanjivanja

Iako strelica u funkciji strelice nije operator, funkcije strelice imaju posebna pravila raščlambe koja drugačije djeluju na prednost operatora u usporedbi s uobičajenim funkcijama.

Neka povratni poziv; povratni poziv = povratni poziv || funkcija(); // ok povratni poziv = povratni poziv || () => (); // SyntaxError: nevažeći argumenti funkcije strelice povratni poziv = povratni poziv || (() => ()); // u redu

Više primjera // Funkcija prazne strelice vraća nedefinirano let empty = () => (); (() => "foobar")(); // Vraća "foobar" // (ovo je izraz funkcije koja se odmah poziva) var simple = a => a > 15 ? 15: a; jednostavan(16); // 15 jednostavno(10); // 10 neka max = (a, b) => a > b ? a: b; // Jednostavno filtriranje polja, mapiranje, ... var arr = ; var sum = arr.reduce((a, b) => a + b); // 66 var even = arr.filter(v => v % 2 == 0); // var double = arr.map(v => v * 2); // // Koncizniji lanci obećanja promise.then(a => ( // ... )).then(b => ( // ... )); // Funkcije strelica bez parametara koje je vizualno lakše analizirati setTimeout(() => ( console.log("Događam se ranije"); setTimeout(() => ( // dublji kod console.log("Događam se kasnije") ; ), jedanaest); Tehnički podaci Komentar statusa specifikacije
ECMAScript 2015 (6. izdanje, ECMA-262)
Standard Početna definicija.
ECMAScript najnoviji nacrt (ECMA-262)
Definicija "Definicije funkcije strelice" u toj specifikaciji.
Nacrt
Kompatibilnost preglednika

Tablica kompatibilnosti na ovoj stranici generirana je iz strukturiranih podataka. Ako želite doprinijeti podacima, pogledajte https://github.com/mdn/browser-compat-data i pošaljite nam zahtjev za povlačenje.

Ažurirajte podatke o kompatibilnosti na GitHubu

Mobilni poslužitelj za stolno računalo Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome za Android Firefox za Android Opera za Android Safari na iOS-u Samsung Internet Node.jsFunkcije strelica Zarez na kraju u parametrima
Chrome Puna podrška 45Edge Potpuna podrška DaFirefox Puna podrška 22

Bilješke

Puna podrška 22

Bilješke

Bilješke Prije Firefoxa 39, završetak retka (\n) bio je pogrešno dopušten nakon argumenata funkcije strelice. Ovo je popravljeno radi usklađivanja sa specifikacijom ES2015 i kodom poput () \n =>
IE Nema podrške brOpera puna podrška 32Safari puna podrška 10WebView Android Puna podrška 45Chrome Android Puna podrška 45Firefox Android Puna podrška 22

Bilješke

Puna podrška 22

Bilješke

Bilješke Početna implementacija funkcija strelica u Firefoxu učinila ih je automatski strogima. Ovo je promijenjeno od Firefoxa 24. Upotreba "use strict"; sada je potrebno. Bilješke Prije Firefoxa 39, završetak retka (\n) bio je pogrešno dopušten nakon argumenata funkcije strelice. Ovo je popravljeno kako bi bilo u skladu sa specifikacijom ES2015, a kod poput () \n => () sada će izbaciti SyntaxError u ovoj i kasnijim verzijama.
Opera Android Puna podrška 32Safari iOS Puna podrška 10Samsung Internet Android Puna podrška 5.0nodejs Puna podrška Da
Chrome Puna podrška 58Rub?Firefox Puna podrška 52IE Nema podrške brOpera puna podrška 45Safari?WebView Android Puna podrška 58Chrome Android Puna podrška 58Firefox Android Puna podrška 52Opera Android Puna podrška 43Safari iOS?Samsung Internet Android Puna podrška 7.0nodejs Puna podrška Da
Legenda Puna podrška Puna podrška Nema podrške Nema podrške Kompatibilnost nepoznata Kompatibilnost nepoznata Vidi napomene o implementaciji. Pogledajte napomene o implementaciji.
  • Tutorial

Jedan od najzanimljivijih dijelova novog standarda ECMAScript 6 su funkcije strelica. Funkcije strelica, kao što ime sugerira, definirane su novom sintaksom koja koristi strelicu => . Međutim, osim po izvrsnoj sintaksi, funkcije strelica razlikuju se od tradicionalnih funkcija na druge načine:

  • Leksičko vezivanje. Vrijednosti posebne varijable this , super i argumenti nisu određeni načinom na koji su funkcije strelica pozvane, već načinom na koji su stvorene.
  • Nepromjenjivo ovo, super i argumenti. Vrijednosti ovih varijabli unutar funkcija strelica ostaju nepromijenjene kroz cijelo vrijeme životni ciklus funkcije.
  • Funkcije strelica ne mogu se koristiti kao konstruktor i stvaraju pogrešku kada se koriste s operatorom new.
  • Nedostupnost "izvorne" vrijednosti varijable argumenata.
Bilo je više razloga za uvođenje ovih razlika. Prvi je da se vezanje prilično često koristi u JavaScriptu. Vrlo je lako izgubiti točnu ovu vrijednost kada koristite tradicionalne funkcije, što može dovesti do neočekivanih posljedica. Drugi razlog je taj što će JS motori moći lako optimizirati izvođenje funkcija strelica zbog ovih ograničenja (za razliku od tradicionalnih funkcija koje se mogu koristiti kao konstruktor i koje je slobodno mijenjati posebne varijable).


Napomena: Ovaj je članak kompilacija besplatnog prijevoda članka Understanding ECMAScript 6 arrow functions i čitanja najnovijeg nacrta specifikacije (20. siječnja 2014. Nacrt Rev. 22).

Sintaksa Općenito, sintaksa funkcija strelica izgleda ovako:

Var zabava = (x) => x;
Vrlo je slična sličnoj sintaksi u jezicima kao što su Scala, CoffeeScript i sintaksi lambda izraza iz C#.

Sintaksa funkcija strelica može se razlikovati ovisno o tome kako deklarirate funkciju. Deklaracija uvijek počinje popisom argumenata, nakon čega slijedi strelica i tijelo funkcije. I popis argumenata i tijelo funkcije mogu imati različite oblike, ovisno o tome što pišete.

Jedan parametar Deklaracija funkcije strelice koja uzima jedan argument i jednostavno ga vraća je vrlo jednostavna:

Var odražava = vrijednost => vrijednost; // ekvivalentno var reflect = function(value) ( ​​​​return value; )
Kada funkcija strelice ima samo jedan argument, može se deklarirati bez zagrada. Tijelo funkcije koje slijedi iza strelice također ne mora imati vitičaste zagrade i ne mora sadržavati ključnu riječ return.

Više parametara Ali ako želite deklarirati više od jednog parametra, morate popis parametara staviti u zagrade:

Var sum = (num1, num2) => num1 + num2; // ekvivalentno var sum = function(num1, num2) ( return num1 + num2; );
Funkcija zbroja jednostavno dodaje dva argumenta. Jedina razlika u odnosu na prethodni primjer je prisutnost zagrada i zareza (baš kao u tradicionalnim funkcijama).

Bez parametara Slično tome, funkcija bez argumenata mora imati prazan popis parametara u zagradama:

Var zbroj = () => 1 + 2; // ekvivalentno var sum = function() ( return 1 + 2; );

Tradicionalna sintaksa tijela funkcije Možete koristiti tradicionalnu sintaksu funkcije za tijelo funkcije strelice kada sadrži više od jednog izraza. To jest, stavite funkciju u vitičaste zagrade i dodajte ključnu riječ return:

Var sum = (num1, num2) => ( return num1 + num2; ) // ekvivalentno var sum = function(num1, num2) ( return num1 + num2; );
Tijelo funkcije bit će obrađeno na potpuno isti način kao i klasične funkcije, osim vrijednosti posebne varijable ovo , super i argumenti bit će drugačije vrednovani.

Objektni literal Zasebno treba spomenuti da tijelo funkcije koja ne sadrži vitičaste zagrade i jednostavno vraća objektni literal treba biti zatvoreno u zagradama:

Var getTempItem = id => (( id: id, name: "Temp" )); // ekvivalentno var getTempItem = function(id) ( return ( id: id, name: "Temp" ));
Stavljanje literala objekta u zagrade govori parseru da vitičaste zagrade nisu početak tradicionalne sintakse za tijelo funkcije, već početak literala.

Varijabilni broj parametara Budući da "nativni" objekt argumenata nije dostupan unutar funkcije strelice (vrijednost argumenata leksički je povezana s vrijednošću argumenata tradicionalne funkcije unutar koje je funkcija strelice deklarirana), tada za funkcije strelice s a varijabilni broj parametara iz kojih trebate koristiti ostatak uzorka obrasci destrukturiranja. Primjer:

Var getTempItems = (...rest) => rest; // ekvivalentno var getTempItems = function() ( return .slice.apply(arguments));

Predložak destrukturiranja kao parametar Za potrebe ovog članka ne razmatramo uzorke destrukturiranja - o njima možete pročitati u članku Pregled ECMAScripta 6, sljedeće verzije JavaScripta, iako su te informacije djelomično zastarjele.

Kao što možete vidjeti iz prethodnog primjera, iako funkcija strelice ima samo jedan argument, i dalje morate koristiti zagrade kada koristite obrasci destrukturiranja kao jedini parametar funkcije. Primjeri s drugima šablone:

Var a = ((a)) => a; var b = ([b]) => b;

Korištenje funkcija sa strelicama Postavljanje konteksta Jedan uobičajeni scenarij u JavaScriptu je postavljanje točne vrijednosti this unutar funkcije (vezivanje). Budući da se vrijednost ovoga može promijeniti, ovisno o kontekstu u kojem se funkcija izvršava, moguće je pogrešno djelovati na jedan objekt kada ste mislili nešto sasvim drugo. Pogledajte sljedeći primjer:

Var pageHandler = ( id: "123456", init: function() (document.addEventListener("click", function(event) ( this.doSomething(event.type); // error )); ) , doSomething: function( tip) ( console.log("Handling " + type + " for " + this.id) ) );
U gornjem kodu, objekt pageHandler trebao bi upravljati klikovima na stranici. Metoda init() pridružuje rukovatelj željenom događaju, koji interno poziva this.doSomething() . Međutim, kôd neće raditi ispravno. Referenca na this.doSomething() nije važeća jer ukazuje na objekt dokumenta unutar rukovatelja događajem umjesto na namjeravani pageHandler. Ako pokušate pokrenuti ovaj kod, dobit ćete pogrešku jer objekt dokumenta nema metodu doSomething.

Možete vezati ovu vrijednost na objekt pageHandler koristeći handleEvent ili pozivanjem standardne metode bind() na funkciji:

Var pageHandler = ( id: "123456", init: function() (document.addEventListener("click", (function(event) ( this.doSomething(event.type); // error )).bind(this)) ; ), doSomething: function(type) ( console.log("Handling " + type + " for " + this.id) ));
Sada kod radi kako je predviđeno, ali izgleda glomaznije. Osim toga, pozivom bind(this) svaki put kada stvorite novu funkciju čija je ova vrijednost povezana s vrijednošću pageHandlera, ali kod radi kako ste namjeravali.

Funkcije strelica rješavaju problem na elegantniji način jer koriste leksičko vezivanje za vrijednost this (kao i super i argumente), a njezina vrijednost određena je vrijednošću this na mjestu gdje je funkcija strelice stvorena. Na primjer:

Var pageHandler = ( id: "123456", init: function() ( document.addEventListener("click", event => this.doSomething(event.type)); ), doSomething: function(type) ( console.log( "Rukovanje " + tip + " za " + this.id) ) );
U ovom primjeru, rukovatelj je funkcija strelice koja poziva this.doSomething() . Vrijednost ovoga bit će ista kao u funkciji init(), a kod u u ovom primjeru radit će ispravno, slično onom koji je koristio bind() . Bez obzira vraća li poziv this.doSomething() vrijednost ili ne, izraz unutar tijela funkcije strelice ne mora biti u vitičastim zagradama.

Osim toga, gornji primjer također je učinkovitiji od pozivanja bind() jer je isti kao sljedeći kod za preglednik:

Var pageHandler = ( id: "123456" , init: function() ( var self = this; document.addEventListener("click", function(event) ( return self.doSomething(event.type) )); ) , doSomething: funkcija(tip) ( console.log("Rukovanje " + tip + " za " + this.id) ));
Odnosno, stvaranje se ne događa nova značajka, kao što je slučaj s pozivom bind().

"Bacanje" konteksta između nekoliko poziva Očito, možete ugnijezditi jednu funkciju strelice unutar druge, čime "bacite" ovu vrijednost kroz njih:

Var obj = ( arr1: , arr2: ["a", "b", "c"] , spoj: funkcija(a, b)( return a + "|" + b ) , presjek: funkcija() ( vrati ovo .arr1.reduce((sum, v1) => // funkcija strelice 1 this.arr2.reduce((sum, v2) => ( // funkcija strelice 2 sum.push(this.concatenate(v1, v2)) return zbroj;) , zbroj) , ) ); var arrSum = obj.intersection();//["1|a", "1|b", "1|c", "2|a", "2|b", "2|c", "3 |a", "3|b", "3|c"]

Upotreba kao argument Kratka sintaksa funkcija strelica čini ih idealnim kandidatima za prosljeđivanje kao argumenata drugim pozivima funkcija. Na primjer, ako želite sortirati niz, obično biste napisali nešto poput ovoga:

Var rezultat = values.sort(function(a, b) ( return a - b ));
Prilično opširno za jednostavnu operaciju. Usporedite s kratkim zapisom za funkciju strelice:

Var result = values.sort((a, b) => a - b);
Korištenje metoda kao što su array(), map(), reduce() i tako dalje može se pojednostaviti korištenjem sintakse kratke funkcije strelice.

Ostale značajke funkcija strelica Iako se funkcije strelica razlikuju od tradicionalnih funkcija, imaju neke zajedničke značajke:
  • Operator typeof vratit će "function" za funkciju strelice
  • Funkcija strelice također je instanca "klase" funkcije, tako da će instanceof raditi isto kao i s tradicionalnom funkcijom
  • I dalje možete koristiti metode call(), apply() i bind(), ali zapamtite da one neće utjecati na vrijednost ovog
  • Možete koristiti metodu toMethod(), no ona neće promijeniti vrijednost super ( metoda toMethod() uvedena je u es6 i nije obuhvaćena ovim člankom).
Značajna razlika u odnosu na tradicionalne funkcije je u tome što će pokušaj pozivanja funkcije strelice pomoću novog operatora uzrokovati pogrešku u vremenu izvođenja. Sažetak Funkcije strelica su jedna od najzanimljivijih inovacija u ECMAScriptu 6, koja će, uz sažetu sintaksu definicije, pojednostaviti prosljeđivanje funkcija kao vrijednosti parametra drugoj funkciji.

Sažeta sintaksa omogućit će vam da složenije stvari napišete još složenije na jednostavniji način. Na primjer, ovako će izgledati generator identifikatora (što izgleda puno opširnije na es5):

Neka idGen = (start = 0, id = start, reset = (newId = start) => id = newId, next = () => id++) => ((reset, next)); neka gen = idGen(100); console.log(gen.next(), gen.next(), gen.reset(10), gen.next());//100 101 10 10
A leksičko uvezivanje zatvorit će jedan od najvećih izvora boli i frustracije za programere, a također će poboljšati performanse zbog optimizacije na razini js motora.


Ako želite isprobati funkcije strelica, možete pokrenuti gornje primjere u Firefox konzoli, koja je uključena ovaj trenutak(02.2014 FF28) gotovo u potpunosti podržava funkcije strelica (FF28 netočno izračunava vrijednost argumenata).

Također možete isprobati funkcije strelica i druge značajke es6 u online prevoditelju Traceur.

Oznake: Dodajte oznake