Funkcie šípok PHP. ES6. Funkcie šípok v javascripte. Pasca: ako nezabudnúť na nové

  • Návod

Jednou z najzaujímavejších častí nového štandardu ECMAScript 6 sú funkcie šípok. Funkcie šípok, ako už názov napovedá, sú definované novou syntaxou, ktorá používa šípku => . Okrem vynikajúcej syntaxe sa však funkcie šípok od tradičných funkcií líšia aj inými spôsobmi:

  • Lexikálna väzba. hodnoty špeciálne premenné argumenty this , super a nie sú určené tým, ako boli funkcie šípok volané, ale tým, ako boli vytvorené.
  • Nemenné toto , super a argumenty . Hodnoty týchto premenných v rámci funkcií šípok zostávajú nezmenené počas životnosti funkcie.
  • Funkcie šípok nemožno použiť ako konštruktor a pri použití s ​​operátorom new vyvolávajú chybu.
  • Nedostupnosť „natívnej“ hodnoty premennej argumenty.
Dôvodov na zavedenie týchto rozdielov bolo niekoľko. Prvým je, že väzba sa v JavaScripte používa pomerne často. Pri používaní tradičných funkcií je veľmi ľahké stratiť správnu túto hodnotu, čo môže viesť k neočakávaným následkom. Ďalším dôvodom je, že motory JS budú môcť vďaka týmto obmedzeniam jednoducho optimalizovať vykonávanie funkcií šípok (na rozdiel od tradičných funkcií, ktoré možno použiť ako konštruktor a môžu sa voľne upravovať špeciálne premenné).


Poznámka: Tento článok je kompiláciou z voľného prekladu článku Pochopenie funkcií šípok ECMAScript 6 a čítania najnovšieho návrhu špecifikácie (20. januára 2014, návrh Rev 22).

Syntax Vo všeobecnosti syntax funkcií šípok vyzerá takto:

Var fun = (x) => x;
Je veľmi podobná podobnej syntaxi v jazykoch ako Scala, CoffeeScript a syntaxi lambda výrazov z C#.

Syntax funkcií šípok sa môže líšiť v závislosti od toho, ako funkciu deklarujete. Deklarácia vždy začína zoznamom argumentov, za ktorými nasleduje šípka a telo funkcie. Zoznam argumentov aj telo funkcie môžu mať rôzne formy v závislosti od toho, čo píšete.

Jeden parameter Deklarovanie funkcie šípky, ktorá vezme jeden argument a jednoducho ho vráti, je veľmi jednoduché:

Var odráža = hodnota => hodnota; // ekvivalent k var reflect = function(value) (return value; )
Keď má funkcia šípky iba jeden argument, možno ju deklarovať bez zátvoriek. Telo funkcie za šípkou tiež nemusí mať žiadne zložené zátvorky a nemusí obsahovať kľúčové slovo return.

Viaceré parametre Ak však chcete deklarovať viac ako jeden parameter, musíte zoznam parametrov uzavrieť do zátvoriek:

Var sum = (num1, num2) => num1 + num2; // ekvivalent k var sum = function(num1, num2) ( return num1 + num2; );
Funkcia súčtu jednoducho pridá dva argumenty. Jediný rozdiel oproti predchádzajúcemu príkladu je prítomnosť zátvoriek a čiarky (rovnako ako v tradičných funkciách).

Žiadne parametre Podobne funkcia bez akýchkoľvek argumentov musí mať prázdny zoznam parametrov uzavretý v zátvorkách:

Var súčet = () => 1 + 2; // ekvivalent k var sum = function() ( return 1 + 2; );

Tradičná syntax tela funkcie Pre telo funkcie šípky môžete použiť tradičnú syntax funkcie, ak obsahuje viac ako jeden výraz. To znamená, že zabaľte funkciu do zložených zátvoriek a pridajte kľúčové slovo return:

Var sum = (num1, num2) => ( return num1 + num2; ) // ekvivalent k var sum = function(num1, num2) ( return num1 + num2; );
Telo funkcie bude spracované úplne rovnako ako pri klasických funkciách, až na to, že hodnoty špeciálne premenné toto , super a argumenty budú hodnotené inak.

Objektový literál Samostatne by sa malo spomenúť, že telo funkcie, ktorá neobsahuje zložené zátvorky a jednoducho vracia objektový literál, by malo byť uzavreté v zátvorkách:

Var getTempItem = id => (( id: id, názov: "Temp" )); // ekvivalent k var getTempItem = function(id) ( return ( id: id, name: "Temp" ) );
Umiestnenie literálu objektu do zátvoriek hovorí syntaktickému analyzátoru, že zložené zátvorky nie sú začiatkom tradičnej syntaxe tela funkcie, ale začiatkom literálu.

Premenlivý počet parametrov Keďže objekt „native“ arguments nie je dostupný vo vnútri funkcie šípky (hodnota argumentov je lexikálne príbuzná hodnote argumentov tradičnej funkcie, v rámci ktorej bola funkcia šípky deklarovaná), potom pre funkcie šípok s variabilný počet parametrov, z ktorých musíte použiť zvyšok vzoru deštruktívne vzory. Príklad:

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

Šablóna deštrukcie ako parameter Na účely tohto článku neuvažujeme o deštruktívnych vzoroch - môžete si o nich prečítať v článku Prehľad ECMAScript 6, ďalšej verzie JavaScriptu, aj keď sú tieto informácie čiastočne zastarané.

Ako môžete vidieť z predchádzajúceho príkladu, aj keď má funkcia šípky iba jeden argument, stále musíte pri použití deštruktívne vzory ako jediný parameter funkcie. Príklady s ostatnými šablón:

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

Používanie funkcií šípok Nastavenie kontextu Jedným bežným scenárom v JavaScripte je nastavenie správnej tejto hodnoty vo funkcii (väzba). Pretože hodnota tohto sa môže meniť v závislosti od kontextu, v ktorom sa funkcia vykonáva, je možné omylom pôsobiť na jeden objekt, keď ste mysleli niečo úplne iné. Pozrite si nasledujúci príklad:

Var pageHandler = ( id: "123456" , init: function() ( document.addEventListener("click", function(event) ( this.doSomething(event.type); // error )); ), doSomething: function( typ) ( console.log("Obsluha " + typ + " pre " + toto.id) ) );
Vo vyššie uvedenom kóde by mal objekt pageHandler spracovávať kliknutia na stránku. Metóda init() pripojí k požadovanej udalosti handler, ktorý interne volá this.doSomething() . Kód však nebude fungovať správne. Odkaz na this.doSomething() nie je platný, pretože ukazuje na objekt dokumentu vo vnútri obsluhy udalosti namiesto zamýšľaného pageHandler . Ak sa pokúsite spustiť tento kód, zobrazí sa chyba, pretože objekt dokumentu nemá metódu doSomething.

Hodnotu this môžete naviazať na objekt pageHandler pomocou handleEvent alebo volaním štandardnej metódy bind() vo funkcii:

Var pageHandler = ( id: "123456" , init: function() ( document.addEventListener("click", (function(event) ( this.doSomething(event.type); // error )).bind(this)) ), doSomething: function(type) ( console.log("Spracovanie " + zadajte + " pre " + toto.id) ) );
Teraz kód funguje tak, ako má, ale vyzerá ťažkopádnejšie. Okrem toho volaním bind(this) zakaždým, keď vytvoríte novú funkciu, ktorej hodnota je prepojená s hodnotou pageHandler , ale kód funguje tak, ako ste zamýšľali.

Funkcie šípok riešia problém elegantnejším spôsobom, pretože pre hodnotu this (rovnako ako super a argumenty) používajú lexikálnu väzbu a jej hodnota je určená hodnotou this v mieste, kde bola funkcia šípky vytvorená. Napríklad:

Var pageHandler = ( id: "123456" , init: function() ( document.addEventListener("click", event => this.doSomething(event.type)); ) , doSomething: function(type) ( console.log( "Obsluha " + zadajte + " pre " + this.id) ) );
V tomto príklade je handlerom funkcia šípky, ktorá volá this.doSomething() . Hodnota tohto bude rovnaká ako vo funkcii init() a kód v tomto príklade bude fungovať správne, podobne ako ten, ktorý použil bind(). Bez ohľadu na to, či volanie this.doSomething() vráti hodnotu alebo nie, výraz v tele funkcie šípky nemusí byť uzavretý do zložených zátvoriek.

Okrem toho je vyššie uvedený príklad efektívnejší ako volanie bind(), pretože je rovnaký ako nasledujúci kód pre prehliadač:

Var pageHandler = ( id: "123456" , init: function() ( var self = toto; document.addEventListener("click", function(event) ( return self.doSomething(event.type) )); ), doSomething: function(type) ( console.log("Obsluha " + typ + " for " + this.id) ) );
To znamená, že sa nevytvorí nová funkcia, ako je to v prípade volania bind() .

„Vhadzovanie“ kontextu medzi niekoľkými hovormi Je zrejmé, že jednu funkciu šípky môžete vložiť do druhej, čím cez ne „prehodíte“ túto hodnotu:

Var obj = ( arr1: , arr2: ["a", "b", "c"] , zreťaziť: function(a, b)( return a + "|" + b ) , intersection: function() ( return this .arr1.reduce((sum, v1) => // funkcia šípky 1 this.arr2.reduce((sum, v2) => ( // funkcia šípky 2 sum.push(this.concatenate(v1, v2)) return súčet ) , súčet) , ) )); var arrSum = obj.intersection();//["1|a", "1|b", "1|c", "2|a", "2|b", "2|c", "3 |a", "3|b", "3|c"]

Použitie ako argument Krátka syntax funkcií šípok z nich robí ideálnych kandidátov na odovzdanie ako argumenty iným volaniam funkcií. Napríklad, ak chcete triediť pole, zvyčajne by ste napísali niečo takéto:

Var vysledok = hodnoty.sort(funkcia(a, b) ( return a - b ));
Docela podrobný pre jednoduchú obsluhu. Porovnajte s krátkym zápisom funkcie šípky:

Var vysledok = hodnoty.sort((a, b) => a - b);
Použitie metód ako array() , map() , reduction() atď. možno zjednodušiť pomocou syntaxe funkcie krátkej šípky.

Ďalšie funkcie funkcií šípok Aj keď sa funkcie šípok líšia od tradičných funkcií, majú niektoré spoločné vlastnosti:
  • Operátor typeof vráti "funkciu" pre funkciu šípky
  • Funkcia šípky je tiež inštanciou triedy Function, takže instanceof bude fungovať rovnako ako tradičná funkcia
  • Stále môžete použiť metódy call() , apply() a bind(), ale nezabudnite, že neovplyvnia hodnotu tohto
  • Môžete použiť metódu toMethod(), nezmení však hodnotu super ( Metóda toMethod() bola zavedená v es6 a tento článok ju nepokrýva).
Významný rozdiel oproti tradičným funkciám spočíva v tom, že pokus o zavolanie funkcie šípky pomocou operátora new spôsobí chybu pri behu. Zhrnutie Funkcie šípok sú jednou z najzaujímavejších noviniek v ECMAScript 6, ktoré vďaka stručnej syntaxi definícií zjednodušia prácu. odovzdávanie funkcií ako hodnoty parametra inej funkcii.

Stručná syntax vám umožní písať zložité veci ešte zložitejšie a jednoduchším spôsobom. Napríklad takto bude vyzerať generátor identifikátorov (ktorý na es5 vyzerá oveľa podrobnejšie):

Nech idGen = (start = 0, id = štart, reset = (newId = start) => id = newId, next = () => id++) => ((reset, next)); nech gen = idGen(100); console.log(gen.next(), gen.next(), gen.reset(10), gen.next());//100 101 10 10
A lexikálna väzba uzavrie jeden z najväčších zdrojov bolesti a frustrácie pre vývojárov a tiež zlepší výkon vďaka optimalizácii na úrovni js enginu.


Ak si chcete funkcie šípok vyskúšať, vyššie uvedené príklady môžete spustiť v konzole Firefoxu, ktorá momentálne (02/2014 FF28) takmer plne podporuje funkcie šípok (FF28 nevyhodnocuje správne hodnotu argumentov ).

Môžete tiež vyskúšať funkcie šípok a ďalšie funkcie es6 v ​​online prekladači Traceur.

Štítky: Pridajte štítky

O kľúčovom slove JavaScript „toto“: funkcie používania s vysvetleniami

Tajomstvo tohto

Kľúčové slovo this pre mňa dlho zostávalo záhadou. Je to mocný nástroj, ale nie je ľahké ho pochopiť.

Z pohľadu Javy, PHP alebo akéhokoľvek iného regulárneho jazyka sa to považuje za inštanciu aktuálneho objektu v metóde triedy, nič viac a nič menej. Najčastejšie ho nemožno použiť mimo metódy a tento prístup nie je nesprávne pochopený.

V JavaScripte je to aktuálny kontext vykonávania funkcie. Pretože funkciu možno volať štyrmi spôsobmi:

  • volanie funkcie: alert("Ahoj svet!"),
  • volanie metódy: console.log("Ahoj svet!"),
  • volanie konštruktora: new RegExp("\\d") ,
  • nepriame volanie: alert.call(nedefinované, "Ahoj svet!") ,

a každý z nich definuje svoj vlastný kontext, správanie tohto je mierne v rozpore s tým, čo by očakávali začínajúci vývojári. Okrem toho prísny režim ovplyvňuje aj kontext vykonávania.

Kľúčom k pochopeniu kľúčového slova this je pochopiť, ako sa funkcia volá a ako ovplyvňuje kontext. Tento článok popisuje volania funkcií, vplyv volaní na to a bežné úskalia pri identifikácii kontextu.

Skôr než začneme, zoznámime sa s niekoľkými pojmami:

  • Volanie je vykonanie kódu tela funkcie. Napríklad volanie funkcie parseInt by bolo parseInt("15") .
  • Kontext volania je hodnota this v tele funkcie.
  • Rozsah funkcie je množina premenných, objektov a funkcií, ku ktorým je možné pristupovať z tela funkcie.

  • 2.1.
    2.2.
    2.3.

  • 3.1.
    3.2.

  • 4.1.
    4.2.

  • 5.1.
  • S
    6.1.

  • 7.1.
    7.2.
  • Volanie funkcie

    Volanie funkcie sa uskutoční, keď za výrazom, ktorý je funkčným objektom, nasleduje otvorená zátvorka (, čiarkami oddelený zoznam argumentov a uzatváracia zátvorka), napríklad parseInt("18") . Výraz nemôže byť prístupovým objektom k myObject.myFunction, ktorý vykonáva volanie metódy. Napríklad .join("") nie je volanie funkcie, ale volanie metódy.

    Jednoduchý príklad volania funkcie:

    Funkcia hello(name) ( return "Ahoj " + meno + "!"; ) // Vyvolanie funkcie var message = hello("World"); console.log(správa); // => "Ahoj Svet!"

    hello("World") je volanie funkcie: hello sa považuje za funkčný objekt, za ktorým nasleduje argument "World" v zátvorkách.

    Var message = (funkcia(meno) ( return "Ahoj " + meno + "!"; ))("Svet"); console.log(správa); // => "Ahoj Svet!"

    Toto je tiež volanie funkcie: prvý pár zátvoriek (funkcia(názov) (...)) sa považuje za funkčný objekt, za ktorým nasleduje argument v zátvorkách: ("Svet").

    toto pri volaní funkcie

    toto je globálny objekt pri volaní funkcie

    Globálny objekt je definovaný runtime. Vo webovom prehliadači je to objekt okna.

    Pri volaní funkcie je kontext vykonávania globálny objekt. Pozrime sa na kontext nasledujúcej funkcie:

    Funkcia sum(a, b) ( console.log(toto === okno); // => true this.myNumber = 20; // pridanie vlastnosti "mojecislo" ku globálnemu objektu return a + b; ) // sum( ) sa vyvoláva ako funkcia // toto v sum() je globálny objekt (okno) console.log(sum(15, 16)); // => 31 console.log(window.myNumber); // => 20

    Keď sa volá sum(15, 16), JavaScript to automaticky inicializuje ako globálny objekt, ktorým je okno v prehliadači.

    Keď sa to použije mimo rozsahu akejkoľvek funkcie (najvzdialenejší rozsah: globálny kontext vykonávania), vzťahuje sa to aj na globálny objekt:

    Console.log(toto === okno); // => true this.myString = "Ahoj Svet!"; console.log(window.myString); // => "Ahoj Svet!" console.log(toto === okno); // => pravda

    toto pri volaní funkcie v prísnom režime

    toto nie je definované pri volaní funkcie v striktnom režime

    /* jshint esnext: true */ class Mesto ( constructor(name, cestoval) ( this.name = name; this.traveled = false; ) travel() ( this.traveled = true; ) ) // Vyvolanie konštruktora var paris = new City("Paris", false); paris.travel();

    new City("Paris") je volanie konštruktora. Inicializácia objektu je riadená špeciálnou metódou triedy: konstruktor , ktorého toto je novovytvorený objekt.

    Volaním konštruktora sa vytvorí nový prázdny objekt, ktorý zdedí vlastnosti z prototypu konštruktora. Úlohou funkcie konštruktora je inicializovať objekt. Ako už viete, kontext tohto typu hovoru sa nazýva inštancia. Toto je téma nasledujúcej kapitoly.

    Keď prístupovému objektu myObject.myFunction predchádza nové kľúčové slovo, JavaScript vykoná volanie konštruktora a nie volanie metódy. Vezmime si ako príklad new myObject.myFunction(): najprv sa pomocou prístupového objektu extractFunction = myObject.myFunction funkcia extrahuje a potom sa volá ako konštruktor na vytvorenie nového objektu: new extractFunction() .

    toto vo volaní konštruktora

    toto je novovytvorený objekt

    Kontextom volania konštruktora je novovytvorený objekt. Používa sa na inicializáciu objektu s údajmi z argumentu funkcie konštruktora.

    Pozrime sa na kontext v nasledujúcom príklade:

    Funkcia Foo () ( console.log(this instanceof Foo); // => true this.property = "Predvolená hodnota"; ) // Vyvolanie konštruktora var fooInstance = new Foo(); console.log(fooInstance.property); // => "Predvolená hodnota"

    new Foo() zavolá konštruktor s kontextom fooInstance . Objekt je inicializovaný vo Foo: this.property je nastavený na predvolenú hodnotu.

    To isté sa stane pri použití triedy , iba inicializácia nastáva v metóde konštruktora:

    /* jshint esnext: true */ class Bar ( constructor() ( console.log(this instanceof Bar); // => true this.property = "Predvolená hodnota"; ) ) // Vyvolanie konštruktora var barInstance = new Bar( ); console.log(barInstance.property); // => "Predvolená hodnota"

    Keď sa spustí new Bar(), JavaScript vytvorí prázdny objekt a urobí z neho kontext metódy konštruktora. Teraz môžete pridať vlastnosti pomocou tohto: this.property = "Predvolená hodnota" .

    Pasca: ako nezabudnúť na nové

    Niektoré funkcie JavaScriptu vytvárajú inštancie, keď sa volajú nielen ako konštruktor, ale aj ako funkcia. Napríklad RegExp:

    Var reg1 = new RegExp("\\w+"); var reg2 = RegExp("\\w+"); console.log(reg1 instanceof RegExp); // => true console.log(reg2 instanceof RegExp); // => true console.log(reg1.source === reg2.source); // => pravda

    Keď sa spustia nové RegExp("\\w+") a RegExp("\\w+"), JavaScript vytvorí ekvivalentné objekty regulárneho výrazu.

    Použitie volania funkcie na vytvorenie objektu je potenciálne nebezpečné (ak vynecháte továrenskú metódu), pretože niektoré konštruktory nemusia inicializovať objekt pri absencii nového kľúčového slova.

    Nasledujúci príklad ilustruje problém:

    Funkcia Vehicle(type, wheelsCount) ( this.type = type; this.wheelsCount = wheelsCount; return this; ) // Vyvolanie funkcie var car = Vehicle("Car", 4); console.log(car.type); // => "Auto" console.log(car.wheelsCount); // => 4 console.log(auto === okno); // => pravda

    Vehicle je funkcia, ktorá nastavuje vlastnosti typu a wheelCount kontextového objektu. Pri spustení Vehicle("Car", 4) vráti objekt car so správnymi vlastnosťami: car.type sa rovná "Car" a car.wheelsCount je 4 . Je ľahké si myslieť, že všetko funguje tak, ako má.

    Pri volaní funkcie je to však objekt okna a Vehicle("Car", 4) nastavuje vlastnosti objektu okna - ups, niečo sa pokazilo. Nový objekt nebol vytvorený.

    Uistite sa, že používate nový operátor, keď sa očakáva volanie konštruktora:

    Funkcia Vehicle(type, wheelsCount) ( if (!(this instanceof Vehicle)) ( throw Error("Chyba: Nesprávne vyvolanie"); ) this.type = type; this.wheelsCount = wheelsCount; return this; ) // Vyvolanie konštruktora var auto = nove vozidlo("Auto", 4); console.log(car.type); // => "Auto" console.log(car.wheelsCount); // => 4 console.log(car instanceof Vehicle); // => true // Vyvolanie funkcie. Vygeneruje chybu. var brokenCar = Vehicle("Broken Car", 3);

    new Vehicle("Car", 4) funguje správne: vytvorí sa a inicializuje nový objekt, pretože je prítomné slovo new.

    Do volania funkcie bolo pridané overenie: táto inštancia vozidla, aby sa zabezpečilo, že kontext vykonávania má správny typ objektu. Ak toto nie je Vozidlo, vygeneruje sa chyba. Ak sa teda vozidlo ("Broken Car", 3) vykoná (bez nového), vyvolá sa výnimka: Chyba: Nesprávne vyvolanie .

    Nepriamy hovor

    Nepriame volanie sa uskutoční, keď je funkcia volaná metódami .call() alebo .apply().

    /* jshint esnext: true */ var sumArguments = (...argumenty) => ( console.log(typeof arguments); // => "undefined" return args.reduce((výsledok, položka) => výsledok + položka ); console.log(sumArguments.name); // => "" console.log(sumArguments(5, 5, 6)); // => 16

    toto vo funkcii šípky

    toto je kontext, v ktorom je funkcia šípky definovaná

    Funkcia šípky nevytvára svoj vlastný kontext vykonávania, ale požičiava si ho z externej funkcie, v ktorej je definovaná.

    Nasledujúci príklad ukazuje transparentnosť kontextu:

    /* jshint esnext: true */ class Point ( konstruktor(x, y) ( this.x = x; this.y = y; ) log() ( console.log(this === myPoint); setTimeout(() => ( console.log(this === myPoint); // => true console.log(this.x + ":" + this.y); // => "95:165" ), 1000); ) ) var myPoint = new Point(95, 165); myPoint.log();

    setTimeout volá funkciu šípky v rovnakom kontexte (metóda myPoint) ako metóda log(). Ako vidíme, funkcia šípky „zdedí“ kontext funkcie, v ktorej je definovaná.

    Ak sa v tomto príklade pokúsite použiť bežnú funkciu, vytvorí si vlastný kontext (okno alebo nedefinovaný). Preto, aby kód správne fungoval, je potrebné manuálne naviazať kontext: setTimeout(function() (...).bind(this)) . Je to ťažkopádne, takže je jednoduchšie použiť funkciu šípky.

    Ak je funkcia šípky definovaná mimo všetkých funkcií, jej kontext je globálny objekt:

    /* jshint esnext: true */ var getContext = () => ( console.log(this === okno); // => true return this; ); console.log(getContext() === okno); // => pravda

    Funkcia šípky je raz a navždy spojená s lexikálnym kontextom. to sa nedá zmeniť ani pomocou metódy zmeny kontextu:

    /* jshint esnext: true */ var cisla = ; (function() ( var get = () => ( return this; ); console.log(this === čísla); // => true console.log(get()); // => // Použiť funkcia šípky s .apply() a .call() console.log(get.call()); // => console.log(get.apply() // => // Zviazať console.log(get .bind()()); // => )).volajte(cisla);

    Funkcia volaná nepriamo pomocou .call(čísla) to nastaví na hodnotu čísla . Funkcia šípky get tiež dostáva čísla, pretože berie kontext lexikálne. Bez ohľadu na to, ako sa get volá, jeho kontext budú vždy čísla . Nepriame volanie s iným kontextom (pomocou .call() alebo .apply()), opätovné spájanie (pomocou .bind()) nebude mať žiadny účinok.

    Funkciu šípky nemožno použiť ako konštruktor. Ak zavoláte new get() , JavaScript vyvolá chybu: TypeError: get nie je konštruktor .

    Úskalia: Definovanie metódy pomocou funkcie šípky

    Možno budete chcieť použiť funkciu šípky na deklarovanie metódy. Spravodlivé: ich deklarácie sú oveľa kratšie v porovnaní s bežným výrazom: (param) => (...) namiesto function(param) (..) .

    Tento príklad demonštruje definovanie metódy format() triedy Period pomocou funkcie šípky:

    /* jshint esnext: true */ funkcia Period (hodiny, minúty) ( this.hours = hours; this.minutes = minutes; ) Period.prototype.format = () => ( console.log(toto === okno) ; // =>

    Keďže formát je funkcia šípky definovaná v globálnom kontexte, toto je objekt okna. Aj keď je formát vykonaný ako metóda objektu walkPeriod.format(), okno zostáva volajúcim kontextom. Stáva sa to preto, že funkcia šípky má statický kontext, ktorý nie je modifikovaný inými typmi volaní.

    toto je okno, takže tieto.hodiny a tieto.minúty sú nedefinované. Metóda vracia reťazec „nedefinované hodiny a nedefinované minúty“, čo nie je požadovaný výsledok.

    Výraz funkcie rieši problém, pretože regulárna funkcia mení svoj kontext v závislosti od volania:

    Obdobie funkcie (hodiny, minúty) ( this.hours = hodiny; this.minutes = minúty; ) Period.prototype.format = function() ( console.log(this === walkPeriod); // => true vráti toto. hodiny + "hodiny a " + toto.minúty + "minúty"); var walkPeriod = new Period(2, 30); console.log(walkPeriod.format());

    walkPeriod.format() je volanie metódy s kontextom walkPeriod. this.hours má hodnotu 2 a this.minute trvá 30 , takže metóda vráti správny výsledok: "2 hours and 30 minutes" .

    Záver

    Keďže volanie funkcie má na to najväčší vplyv, odteraz sa nepýtajte:

    Odkiaľ to pochádza?

    a spýtaj sa:

    Ako sa funkcia volá?

    A v prípade funkcie šípky sa opýtajte:

    Čo je to, kde je deklarovaná funkcia šípky?

    Tento prístup vám ušetrí zbytočné bolesti hlavy.

    Nenechajte sa zmiasť v súvislostiach! 🙂

    Výraz funkcie šípky je syntakticky kompaktnou alternatívou k reguláru funkčný výraz, hoci bez vlastnej väzby na toto , argumenty , Super, alebo nový.cieľ Kľúčové slová. Výrazy funkcie šípok nie sú vhodné ako metódy a nemožno ich použiť ako konštruktory.

    Syntax Základná syntax (param1, param2, …, paramN) => ( príkazy ) (param1, param2, …, paramN) => výraz // ekvivalent: => ( návratový výraz; ) // Zátvorky sú voliteľné, ak je iba jeden názov parametra: (singleParam) => ( príkazy ) singleParam => ( príkazy ) // Zoznam parametrov pre funkciu bez parametrov by mal byť napísaný s párom zátvoriek () => ( príkazy ) Rozšírená syntax // Parenthesize telo funkcie na vrátenie doslovného výrazu objektu: params => ((foo: bar)) // Ostatné parametre a predvolené parametre sú podporované (param1, param2, ...zvyšok) => ( príkazy ) (param1 = predvolená hodnota1, param2, ..., paramN = predvolená hodnotaN) => ( príkazy ) // Zničenie v rámci zoznamu parametrov je podporovaný aj var f = ( = , (x: c) = (x: a + b)) => a + b + c; f(); // 6 Popis

    Zavedenie funkcií šípok ovplyvnili dva faktory: potreba kratších funkcií a správanie kľúčového slova this.

    Kratšie funkcie var prvky = [ "Vodík", "Hélium", "Lítium", "Beryllium" ]; // Tento príkaz vráti prvky poľa:. mapa(funkcia(prvok) ( return element.length; )); // Normálnu funkciu vyššie možno zapísať ako funkciu šípky pod elements.map((element) => ( return element.length; )); // // Keď existuje len jeden parameter, môžeme odstrániť prvky obklopujúce zátvorky. mapa(prvok => ( return element.length; )); // // Keď je jediným príkazom vo funkcii šípky `return`, môžeme odstrániť `return` a odstrániť // okolité zložené zátvorky elements.map(element => element.length); // // V tomto prípade, pretože potrebujeme iba vlastnosť length, môžeme použiť parameter deštrukturovania: // Všimnite si, že `length` zodpovedá vlastnosti, ktorú chceme získať, zatiaľ čo // zjavne nešpeciálna `lengthFooBArX` je len názov premennej, ktorý možno zmeniť // na ľubovoľný platný názov premennej, ktorý chcete použiť. mapa(((dĺžka:dĺžkaFooBArX )) => dĺžkaFooBArX); // // Toto priradenie deštruktívneho parametra je možné zapísať aj tak, ako je uvedené nižšie. Všimnite si však, že v // tomto príklade nepriraďujeme hodnotu `length` k vytvorenej vlastnosti. Namiesto toho sa ako vlastnosť, ktorú chceme z objektu získať, použije doslovný názov // samotný premennej `length`. prvkov. mapa(((dĺžka)) => dĺžka); // Toto nie je oddelené

    Pred funkciami šípok každá nová funkcia definovala svoju vlastnú toto hodnota podľa toho, ako bola funkcia volaná:

    • Nový objekt v prípade konštruktora.
    • nedefinované v prísny režim volania funkcií.
    • Základný objekt, ak bola funkcia volaná ako "metóda objektu".

    Ukázalo sa, že pri objektovo orientovanom štýle programovania to nie je ideálne.

    Funkcia Person() ( // Konštruktor Person() definuje `this` ako svoju inštanciu. this.age = 0; setInterval(function growUp() ( // V neprísnom režime funkcia growUp() definuje ` this` // ako globálny objekt (pretože je to miesto, kde sa vykonáva growUp().), // ktorý sa líši od `this` // definovaného konštruktorom Person(). this.age++; ), 1000) ; ) var p = nová osoba();

    V ECMAScript 3/5 sa tento problém dal vyriešiť priradením hodnoty v tomto premennej, ktorú možno uzavrieť.

    Funkcia Osoba() ( var that = this; that.age = 0; setInterval(function growUp() () ( // Spätné volanie odkazuje na premennú `that`, ktorej // hodnota je očakávaný objekt. that.age++; ) , 1000 ) "použiť prísne"; var obj = (a: 10); Object.defineProperty(obj, "b", ( get: () => ( console.log(this.a, typeof this.a, this); // undefined "undefined" Window (...) (alebo globálne object) return this.a + 10 // predstavuje globálny objekt "Window", preto "this.a" vráti "undefined" ) ));

    Použitie nového operátora

    Funkcie šípok nemožno použiť ako konštruktory a pri použití s ​​novým súborom generujú chybu.

    Var Foo = () => (); var foo = new Foo(); // TypeError: Foo nie je konštruktor

    Použitie vlastnosti prototypu

    Funkcie šípok nemajú vlastnosť prototypu.

    Var Foo = () => (); console.log(Foo.prototype); //nedefinované

    Použitie kľúčového slova výnos

    The výnos Kľúčové slovo sa nesmie použiť v tele funkcie šípky (okrem prípadov, keď je to povolené v rámci funkcií, ktoré sú v ňom ďalej vnorené). V dôsledku toho sa funkcie šípok nedajú použiť ako generátory.

    Funkčné telo

    Funkcie šípok môžu mať buď „stručné telo“ alebo obvyklé „blokové telo“.

    V stručnom tele je špecifikovaný iba výraz, ktorý sa stáva implicitnou návratovou hodnotou. V tele bloku musíte použiť explicitný príkaz return.

    Var func = x => x * x; // stručná syntax tela, implikovaný "return" var func = (x, y) => ( return x + y; ); // s telom bloku, je potrebný explicitný "návrat".

    Vracanie objektových literálov

    Majte na pamäti, že vrátenie objektových literálov pomocou stručných parametrov syntaxe tela => (object:literal) nebude fungovať podľa očakávania.

    Var func = () => ( foo: 1 ); // Volanie funkcie func() vráti hodnotu undefined! var func = () => ( foo: function() () ); // SyntaxError: príkaz funkcie vyžaduje názov

    Je to preto, že kód v zložených zátvorkách (()) je analyzovaný ako postupnosť príkazov (t. j. s foo sa zaobchádza ako s označením, nie ako kľúčom v objektovom literáli).

    Objekt musíte zabaliť do zátvoriek:

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

    Zalomenie riadkov

    Funkcia šípky nemôže obsahovať zalomenie riadku medzi jej parametrami a šípkou.

    Var func = (a, b, c) => 1; // SyntaxError: očakávaný výraz, dostal "=>"

    Dá sa to však zmeniť vložením zalomenia riadka za šípku alebo použitím zátvoriek/zátvoriek, ako je uvedené nižšie, aby sa zabezpečilo, že kód zostane pekný a nadýchaný. Medzi argumenty môžete vložiť aj zlomy riadkov.

    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; // nebola vyvolaná chyba SyntaxError

    Poradie analýzy

    Aj keď šípka vo funkcii šípky nie je operátorom, funkcie šípky majú špeciálne pravidlá analýzy, s ktorými interagujú odlišne prednosť operátora v porovnaní s bežnými funkciami.

    Nechajte spätné volanie; spätné volanie = spätné volanie || funkcia(); // ok spätné volanie = spätné volanie || () => (); // SyntaxError: neplatné argumenty funkcie šípky callback = callback || (() => ()); // dobre

    Ďalšie príklady // Funkcia prázdnej šípky vracia nedefinované nech prázdne = () => (); (() => "foobar")(); // Vráti "foobar" // (toto je Okamžite vyvolaný funkčný výraz) var simple = a => a > 15 ? 15: a; jednoduchý(16); // 15 jednoduchých(10); // 10 nech max = (a, b) => a > b ? a: b; // Jednoduché filtrovanie polí, mapovanie, ... var arr = ; var sum = arr.reduce((a, b) => a + b); // 66 var párne = arr.filter(v => v % 2 == 0); // var double = arr.map(v => v * 2); // // Výstižnejšie reťazce sľubov sľub.then(a => ( // ... )).then(b => ( // ... )); // Funkcie šípok bez parametrov, ktoré sa vizuálne ľahšie analyzujú setTimeout(() => ( console.log("Urobím to skôr"); setTimeout(() => ( // hlbší kód console.log("Urobím to neskôr") ; jedenásť); technické údaje Komentár stavu špecifikácie
    ECMAScript 2015 (6. vydanie, ECMA-262)
    Štandardné Počiatočná definícia.
    Najnovší koncept ECMAScript (ECMA-262)
    Definícia "definície šípkových funkcií" v tejto špecifikácii.
    Návrh
    Kompatibilita prehliadača

    Tabuľka kompatibility na tejto stránke je vygenerovaná zo štruktúrovaných údajov. Ak by ste chceli prispieť k údajom, pozrite si https://github.com/mdn/browser-compat-data a pošlite nám žiadosť o stiahnutie.

    Aktualizujte údaje o kompatibilite na GitHub

    Desktop Mobile Server Chrome Edge Firefox Internet Explorer Opera Safari Webové zobrazenie Android Chrome pre Android Firefox pre Android Opera pre Android Safari na iOS Samsung Internet Node.jsFunkcie šípok Koncová čiarka v parametroch
    Plná podpora prehliadača Chrome 45Plná podpora Edge ÁnoPlná podpora Firefoxu 22

    Poznámky

    Plná podpora 22

    Poznámky

    Poznámky Pred Firefoxom 39 bol za argumentmi funkcie šípky nesprávne povolený znak ukončenia riadku (\n). Toto bolo opravené, aby vyhovovalo špecifikácii ES2015 a kódu ako () \n =>
    IE Žiadna podpora NieOpera plná podpora 32Plná podpora Safari 10WebView Plná podpora pre Android 45Chrome Plná podpora pre Android 45Firefox Plná podpora pre Android 22

    Poznámky

    Plná podpora 22

    Poznámky

    Poznámky Počiatočná implementácia funkcií šípok vo Firefoxe ich automaticky sprísnila. Toto bolo zmenené od verzie Firefox 24. Použitie „use strict“; sa teraz vyžaduje. Poznámky Pred Firefoxom 39 bol za argumentmi funkcie šípky nesprávne povolený znak ukončenia riadku (\n). Toto bolo opravené, aby vyhovovalo špecifikácii ES2015 a kód ako () \n => () teraz v tejto a novších verziách vyvolá chybu SyntaxError.
    Opera Android Plná podpora 32Safari iOS Plná podpora 10Samsung Internet Android Plná podpora 5.0nodejs Plná podpora Áno
    Plná podpora prehliadača Chrome 58Hrana?Plná podpora Firefoxu 52IE Žiadna podpora NieOpera plná podpora 45Safari?WebView Plná podpora pre Android 58Chrome Plná podpora Androidu 58Firefox Plná podpora pre Android 52Opera Android Plná podpora 43Safari iOS?Samsung Internet Android Plná podpora 7.0nodejs Plná podpora Áno
    Legenda Úplná podpora Úplná podpora Žiadna podpora Žiadna podpora Kompatibilita neznáma Kompatibilita neznáma Pozrite si poznámky k implementácii. Pozri implementačné poznámky.