Kako postaviti pametne telefone i računala. Informativni portal
  • Dom
  • OS
  • Funkcionalno programiranje. Funkcije u JavaScriptu

Funkcionalno programiranje. Funkcije u JavaScriptu

Funkcije

Funkcija je blok JavaScript koda koji je definiran jednom i može se izvršiti ili pozvati više puta. Možda ste već upoznati s funkcijom pod drugim imenom, kao što je potprogram ili procedura. Funkcije mogu imati parametre: definicija funkcije može uključivati ​​popis identifikatora, koji se nazivaju parametri i djeluju kao lokalne varijable u tijelu funkcije.

Prilikom pozivanja funkcija mogu im se proslijediti vrijednosti ili argumenti koji odgovaraju njihovim parametrima. Funkcije često koriste svoje argumente za procjenu povratne vrijednosti, koja je vrijednost izraza poziva funkcije. Osim argumenata, prilikom pozivanja bilo koje funkcije, njoj se prosljeđuje još jedna vrijednost koja određuje kontekst poziva - vrijednost u ključnoj riječi ovaj.

Funkcije u JavaScriptu su objekti i mogu se koristiti na razne načine. Na primjer, funkcije se mogu dodijeliti varijablama i proslijediti drugim funkcijama. Budući da su funkcije objekti, moguće je dodijeliti vrijednosti njihovim svojstvima, pa čak i pozvati njihove metode.

JavaScript vam omogućuje stvaranje definicija funkcija koje su ugniježđene unutar drugih funkcija, a takve će funkcije imati pristup svim varijablama prisutnim u opsegu definicije.

Definiranje funkcija

Definicija funkcije počinje ključnom riječi funkcija slijede sljedeće komponente:

Identifikator koji definira naziv funkcije

Ime je obavezan dio izraza deklaracije funkcije: koristit će se za stvaranje nove varijable kojoj će se dodijeliti novi objekt funkcije. Naziv može biti odsutan u izrazima definicije funkcije: ako je prisutan, naziv će se odnositi na objekt funkcije samo u tijelu same funkcije.

Par zagrada oko popisa s nula ili više identifikatora, odvojenih zarezima

Ovi identifikatori će definirati nazive parametara funkcije i mogu se koristiti kao lokalne varijable u tijelu funkcije.

Par vitičastih zagrada s nula ili više JavaScript izjava unutar

Ove upute čine tijelo funkcije: izvršavaju se svaki put kada se funkcija pozove.

Sljedeći primjer prikazuje nekoliko definicija funkcija kao naredbi i izraza. Imajte na umu da su definicije funkcija kao izrazi korisne samo ako su dio većih izraza, kao što su dodjele ili pozivi funkcija, koji rade nešto s novo deklariranom funkcijom:

// Ispisuje imena i vrijednosti svih svojstava funkcije obj objekta printprops (obj) (za (var p u obj) console.log (p + ":" + obj [p] + "\ n"); ) // Izračunava udaljenost između točaka (x1, y1) i (x2, y2) udaljenost funkcije (x1, y1, x2, y2) (var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt ( dx * dx + dy * dy );) // Rekurzivna funkcija (poziva sama sebe) koja izračunava faktorijalnu funkciju factorial (x) (ako (x

Imajte na umu da naziv funkcije možda neće biti prisutan u izrazima definicije funkcije. Naredba deklaracije funkcije zapravo deklarira varijablu i dodjeljuje joj funkcijski objekt.

Nasuprot tome, izraz definicije funkcije ne deklarira varijablu. Međutim, u definicijskim izrazima dopušteno je navesti naziv funkcije, kao u gore navedenoj funkciji za izračunavanje faktorijala, koja može biti potrebna u tijelu funkcije da bi se sama pozvala. Ako izraz definicije funkcije uključuje ime, dano ime će se odnositi na objekt funkcije u opsegu te funkcije. Zapravo, naziv funkcije postaje lokalna varijabla, dostupna samo u tijelu funkcije. U većini slučajeva naziv funkcije nije potrebno specificirati u definicijskim izrazima, što definicije čini kompaktnijim.

Imajte na umu da većina (ali ne sve) funkcija u primjeru sadrži izraz return. Naredba return završava izvršavanje funkcije i vraća vrijednost njenog izraza (ako je specificirano) pozivnom programu. Ako u naredbi return nema izraza, vraća se nedefinirano. Ako u funkciji nema izraza return, tumač će jednostavno izvršiti sve naredbe u tijelu funkcije i vratiti nedefinirano u program koji poziva.

Većina funkcija u primjeru procjenjuje neku vrijednost i koriste izraz return za vraćanje te vrijednosti u program koji poziva. Funkcija printprops () je malo drugačija u tom smislu: njezin je zadatak ispisati nazive svojstava objekta. Ne mora vratiti nikakvu vrijednost, tako da u funkciji nema povratnog izraza. Funkcija printprops () uvijek će vratiti nedefinirano. (Funkcije koje nemaju povratnu vrijednost ponekad se nazivaju postupcima.)

Funkcije poziva

Programski kod koji čini tijelo funkcije ne izvršava se u trenutku kada je funkcija definirana, već u trenutku kada je pozvana. Pozivi funkcija izvode se pomoću izraza za poziv. Izraz poziva sastoji se od izraza poziva funkcije koji vraća objekt funkcije, nakon čega slijede zagrade nakon kojih slijedi popis nula ili više izraza argumenata, odvojenih zarezima, unutar.

Ako je izraz poziva funkcije izraz poziva svojstva - ako je funkcija svojstvo objekta ili element niza (to jest, metoda) - tada je izraz poziva izraz poziva metode. Sljedeći isječak pokazuje nekoliko primjera običnih izraza poziva funkcije:

Rekviziti za ispis ((x: 4, dob: 24)); var d = udaljenost (1,1,5,6); var f = faktorijel (5) / faktorijel (12); f = kvadrat (5);

Kada se funkcija pozove, evaluiraju se svi izrazi argumenata (navedeni između zagrada), a rezultirajuće vrijednosti se koriste kao argumenti funkciji. Ove vrijednosti se dodjeljuju parametrima čija su imena navedena u definiciji funkcije. U tijelu funkcije, izrazi poziva parametara vraćaju vrijednosti odgovarajućih argumenata.

Kada se pozove normalna funkcija, povratna vrijednost funkcije postaje vrijednost pozivajućeg izraza. Ako se funkcija vrati kada interpretator dođe do kraja, povratna vrijednost je nedefinirana. Ako se funkcija vraća kao rezultat povratnog izraza, vraća se vrijednost izraza koji slijedi nakon povratnog izraza ili je nedefinirana ako izraz return nema izraz.

Metoda nije ništa više od funkcije koja je pohranjena kao svojstvo objekta. Ako imate funkciju func i objekt obj, možete definirati metodu na objektu obj pod nazivom method, kao što je prikazano u nastavku:

// Definiraj jednostavan objekt i funkciju var obj = (); funkcija func (a, b) (vraćanje a + b;) // Dodaj metodu obj u obj object.method = func; // Sada možete pozvati ovu metodu var result = obj.method (4, 5);

Najčešće, prilikom pozivanja metoda, koristite oblik pristupa svojstvima pomoću operatora točka, ali na isti način možete koristiti oblik pristupa svojstvima korištenjem uglastih zagrada. Na primjer, oba sljedeća izraza su izrazi za pozivanje metode:

Rezultat = obj.metoda (4, 5); rezultat = obj ["metoda"] (4, 5);

Argumenti i povratna vrijednost poziva metode obrađuju se na isti način kao i obični poziv funkcije. Međutim, pozivanje metode ima jednu važnu razliku: kontekst zazivanja. Izraz pristupa svojstvu sastoji se od dva dijela: objekta (u ovom slučaju obj) i imena svojstva (metoda). U takvim izrazima poziva metode, objekt obj postaje pozivni kontekst, a tijelo funkcije može se referirati na ovaj objekt pomoću ključne riječi this. Na primjer:

Var obj = (x: 0, y: 0, // Dodaj metodu: funkcija (a, b) (this.x = a; this.y = b;), // Drugi zbroj metode: funkcija () (vrati ovo .x + ovo.y)); // Pozivanje metoda obj.add (15, 4); console.log (obj.sum ()); // devetnaest

Metode i ključna riječ this središnje su za paradigmu objektno orijentiranog programiranja. Svaka funkcija koja se koristi kao metoda zapravo prima implicitni argument - objekt na kojem je pozvana. Obično metode izvode neku radnju na objektu, a sintaksa poziva metode jasno odražava činjenicu da funkcija radi na objektu.

Napomena: ovo je samo ključna riječ, a ne naziv varijable ili svojstva. JavaScript sintaksa ne dopušta dodjelu vrijednosti elementu this.

Argumenti i parametri funkcije

U JavaScriptu, tipovi parametara nisu navedeni u definicijama funkcija i ne provode se provjere tipa na proslijeđenim vrijednostima argumenata kada se funkcije pozivaju. Zapravo, prilikom pozivanja funkcija u JavaScriptu, čak se i broj argumenata ne provjerava. Pododjeljci u nastavku opisuju što se događa kada je broj argumenata u pozivu funkcije manji ili veći od broja deklariranih parametara. Oni također pokazuju kako možete eksplicitno provjeriti tipove argumenata funkcije ako trebate osigurati da funkcija nije pozvana s nevažećim argumentima.

Neobavezni argumenti

Kada je broj argumenata u pozivu funkcije manji od broja deklariranih parametara, argumenti koji nedostaju su nedefinirani. Često je prikladno pisati funkcije tako da su neki od argumenata izborni i da se mogu izostaviti kada se funkcija pozove. U ovom slučaju, poželjno je predvidjeti mogućnost dodjeljivanja razumno razumnih zadanih vrijednosti parametrima koji se mogu izostaviti. Na primjer:

// Dodajte nabrojana imena // svojstava objekta obj u niz i vratite ga. Ako argument // arr nije proslijeđen, kreirajte i vratite novu funkciju polja getPropertyNames (obj, / * opcionalno * / arr) (if (arr === nedefinirano) arr =; // Ako polje nije definirano, kreirajte novi za ( svojstvo var u obj) arr.push (property); return arr;) // Ova funkcija se može pozvati s 1 ili 2 argumenta: var a = getPropertyNames ((x: 1, y: 1)); // Dobivanje svojstava objekta u novom nizu getPropertyNames ((z: 5), a); // dodaj svojstva novog objekta u ovaj niz console.log (a); // ["x", "y", "z"]

Imajte na umu da prilikom deklariranja funkcija neobavezni argumenti moraju završiti popis argumenata kako bi bili izostavljeni. Programer koji će napisati poziv vašoj funkciji neće moći proslijediti drugi argument i istovremeno izostaviti prvi: bit će prisiljen eksplicitno proći nedefinirano u prvom argumentu. Obratite pažnju i na komentar / * neobavezno * / u definiciji funkcije, koji naglašava činjenicu da je parametar neobavezan.

Popisi argumenata promjenjive duljine

Ako broj argumenata u pozivu funkcije premašuje broj naziva parametara, funkciji je onemogućen izravan pristup neimenovanim vrijednostima. Rješenje ovog problema pruža Argumenti prigovaraju... U tijelu funkcije, identifikator argumentima odnosi se na objekt Arguments prisutan u pozivu. Objekt Arguments je objekt sličan nizu koji vam omogućuje dohvaćanje vrijednosti proslijeđenih funkciji po broju, a ne po imenu.

Pretpostavimo da je definirana funkcija koja zahtijeva jedan argument, x. Ako ovu funkciju pozovete s dva argumenta, tada će prvi biti dostupan unutar funkcije po imenu parametra x ili kao argumenti. Drugi argument bit će dostupan samo kao argumenti. Osim toga, poput pravih nizova, argumenti imaju svojstvo duljine koje određuje broj elemenata koje treba sadržavati. To jest, u tijelu funkcije koja se zove s dva argumenta, arguments.length je 2.

Objekt Arguments može se koristiti u razne svrhe. Sljedeći primjer pokazuje kako ga koristiti za provjeru je li funkcija pozvana s točnim brojem argumenata, jer JavaScript to neće učiniti umjesto vas:

Funkcija funkcija (x, y, z) (// Prvo, provjerava je li proslijeđen točan broj argumenata if (arguments.length! = 3) (izbaci novu pogrešku ("Function func was called with" + arguments.length + "argumenti, ali 3. ");) // A sada sam kod funkcije ...)

Imajte na umu da često nije potrebno provjeravati broj argumenata, kao u ovom primjeru. Zadano ponašanje JavaScript interpretera izvrsno je u većini slučajeva: nedostajući argumenti zamjenjuju se nedefiniranim, a dodatni argumenti se jednostavno zanemaruju.

Objekt Arguments ilustrira važnu značajku JavaScript funkcija: mogu se napisati da uzimaju bilo koji broj argumenata. Sljedeća funkcija uzima bilo koji broj argumenata i vraća vrijednost najvećeg od njih (ugrađena funkcija Math.max () ponaša se slično):

Funkcija maxNumber () (var m = Broj.NEGATIVE_INFINITY; // Prođite kroz sve argumente, pronađite i // pohranite najveći od njih za (var i = 0; im) m = argumente [i]; // Vratite najveći povrat m ;) var najveći = maksimalni broj (1, 10, 100, 2, 3, 1000, 4, 5, 10000, 6); // 10000

Funkcije poput ove, koje mogu uzeti proizvoljan broj argumenata, nazivaju se varijabilnim funkcijama, varijabilnim aritnim funkcijama ili varargs funkcijama. Ovaj izraz nastao je pojavom programskog jezika C.

Imajte na umu da funkcije s promjenjivim brojem argumenata ne smiju biti pozvane s praznim popisom argumenata. Savršeno je logično koristiti objekt arguments kada pišete funkciju koja očekuje da će primiti fiksni broj potrebnih imenovanih argumenata, nakon čega slijedi proizvoljan broj neobaveznih neimenovanih argumenata.

Imajte na umu da argumenti zapravo nisu niz - oni su objekt Arguments. Svaki objekt Arguments ima numerirane elemente niza i svojstvo duljine, ali tehnički to nije niz. Bolje ga je zamisliti kao objekt s nekim numeriranim svojstvima.

Osim elemenata svog niza, objekt Arguments definira svojstva pozvani i pozivatelja... Pokušaj promjene vrijednosti ovih svojstava u strogom načinu rada ECMAScript 5 zajamčeno će izazvati iznimku TypeError. Međutim, u opuštenom načinu rada, standard ECMAScript navodi da se svojstvo pozivatelja odnosi na funkciju koja se trenutno izvršava. Svojstvo pozivatelja nije standardno, ali je prisutno u mnogim implementacijama i odnosi se na funkciju koja je pozvala trenutnu.

Svojstvo pozivatelja može se koristiti za pristup stogu poziva, a svojstvo pozivatelja posebno je korisno za rekurzivno pozivanje neimenovanih funkcija:

Var faktorijel = funkcija (x) (ako je (x

Svojstva i metode funkcija

Vidjeli smo da se funkcije mogu koristiti kao vrijednosti u JavaScript programima. Operator typeof vraća niz "function" za funkcije, ali funkcije u JavaScriptu su zapravo posebna vrsta objekta. A budući da su funkcije objekti, imaju svojstva i metode kao i svaki drugi objekt. Postoji čak i konstruktor Function () koji stvara nove funkcionalne objekte. Sljedeći pododjeljci opisuju svojstva i metode funkcija.

Svojstvo duljine

U tijelu funkcije svojstvo arguments.length određuje broj argumenata koji se prosljeđuju funkciji. Međutim, svojstvo duljine same funkcije ima drugačije značenje. Ovo svojstvo samo za čitanje vraća broj argumenata koje funkcija očekuje da će primiti - broj deklariranih parametara.

Sljedeći isječak definira funkciju pod nazivom check () koja prima niz argumenata od druge funkcije. Uspoređuje svojstvo arguments.length (broj stvarno proslijeđenih argumenata) sa svojstvom arguments.callee.length (broj očekivanih argumenata) kako bi utvrdio je li funkciji proslijeđeno onoliko argumenata koliko očekuje. Ako se vrijednosti ne podudaraju, izbacuje se iznimka. Nakon funkcije check () slijedi testna funkcija func (), koja pokazuje kako koristiti funkciju check ():

// Ova funkcija koristi arguments.callee, tako da // neće raditi u strogom načinu provjere funkcije (args) (var stvarni = args.length; // Stvarni broj argumenata var očekivan = args.callee.length; // Argumenti očekivanog broja if (stvarno! == očekivano) // Ako se ne podudaraju, izbacite novu pogrešku ("očekivalo se:" + očekivano + "; primljeno" + stvarno);) funkcija funkcija (x, y, z) (/ / Provjerite broj očekivanih i stvarno prošlih argumenata (argumenata); // Sada izvršite ostatak funkcije return x + y + z;)

Svojstvo prototipa

Svaka funkcija ima svojstvo prototipa koje se odnosi na objekt poznat kao objekt prototipa. Svaka funkcija ima svoj vlastiti prototip objekta. Kada se funkcija koristi kao konstruktor, novostvoreni objekt nasljeđuje svojstva tog prototipa objekta.

O prototipovima i svojstvima prototipa raspravljalo se u prethodnom članku.

Pozovite () i primijenite () metode

Metode call () i apply () omogućuju vam da neizravno pozovete funkciju kao da je metoda nekog drugog objekta. Prvi argument i call () i apply () je objekt na kojem se poziva funkcija; ovaj argument definira kontekst poziva i postaje vrijednost ove ključne riječi u tijelu funkcije. Da biste pozvali func () (bez argumenata) kao metodu obj, možete koristiti bilo koju od metoda call () ili apply ():

Func.call (obj); func.primijeniti (obj);

Bilo koja od ovih metoda poziva je ekvivalentna sljedećem isječku (pod pretpostavkom da obj nema svojstvo pod nazivom m):

Obj.m = func; // Privremeno napravi func metodu obj obj.m (); // Nazovite ga bez argumenata. izbrisati obj.m; // Ukloni privremenu metodu.

U strogom načinu rada ECMAScript 5, prvi argument metoda call () i apply () postaje vrijednost this, čak i ako je jednostavna vrijednost, null ili nedefinirana. U ECMAScript 3 i nestrogom načinu rada, null i nedefinirane vrijednosti zamjenjuju se globalnim objektom, a jednostavna vrijednost je zamijenjena odgovarajućim objektom omotača.

Svi ostali argumenti metode call () nakon prvog argumenta koji specificira kontekst poziva prosljeđuju se pozvanoj funkciji. Metoda apply () djeluje kao metoda call (), osim što se argumenti funkciji prosljeđuju kao niz. Ako funkcija može rukovati proizvoljnim brojem argumenata, metoda apply () može se koristiti za pozivanje te funkcije u kontekstu niza proizvoljne duljine.

Sljedeći primjer pokazuje praktičnu upotrebu metode call ():

// Ispod su dvije funkcije koje prikazuju svojstva i // vrijednosti svojstava proizvoljnog objekta. Metoda prikaza // prosljeđuje se kao argument func funkcija print1 (func, obj) (za (n u obj) func (n + ":" + obj [n]);) funkcija print2 (func, objDevice, obj) ( za ( n u obj) func.call (objDevice, n + ":" + obj [n]);) var obj = (x: 5, y: 10); print2 (document.write, document, obj); // Radi ispravno print2 (console.log, console, obj); print1 (document.write, obj); // Izuzetak nezakonitog pozivanja bit će izbačen jer print1 (console.log, obj); // nemoguće je pozvati ove metode bez objekta konteksta

Bind () metoda

Metoda bind () prvi put se pojavila u ECMAScript-u 5, ali ju je lako oponašati u ECMAScript-u 3. Kao što joj naziv govori, glavna svrha metode bind () je vezati funkciju na objekt. Ako pozovete bind () metodu func i proslijedite joj objekt obj, vratit će novu funkciju. Pozivanje nove funkcije (poput normalne funkcije) pozvat će izvornu func funkciju kao metodu obj. Svi argumenti proslijeđeni novoj funkciji bit će proslijeđeni izvornoj funkciji. Na primjer:

// Funkcija za vezanje funkcije func (y) (vrati this.x + y;) var obj = (x: 1); // Objekt za povezivanje s var g = func.bind (obj); // Pozivanje g (x) će pozvati obj.func (x)

Ovaj način povezivanja lako je implementirati u ECMAScript 3, kao što je prikazano u nastavku:

// Vraća funkciju koja poziva func kao metodu obj // i prosljeđuje joj sve svoje argumente function bind (func, obj) (if (func.bind) return func.bind (obj); // Koristi metodu bind, ako postoji else return funkcija () (// Else vezanje kao ispod vrati func.apply (obj, argumenti););)

Bind () metoda u ECMAScript 5 ne veže samo funkciju na objekt. Također radi djelomičnu primjenu: osim vrijednosti this, svi argumenti proslijeđeni bind () nakon prvog argumenta bit će vezani. Djelomična primjena uobičajena je tehnika u funkcionalnom programiranju i ponekad se naziva currying.

Članak je u izradi!

Članak u kojem ćemo razmotriti što je funkcija, kao i tradicionalnu (klasičnu) verziju rada s njom. Osim toga, analizirat ćemo koji su argumenti (parametri) funkcije i operator return.

Što je funkcija?

Funkcija je neka skup uputa kojem se može dati ime i onda nazivati ​​ga ovim imenom s bilo kojeg mjesta u programu.

Klasičan primjer korištenja funkcije. Web stranica ima JavaScript kod, neki fragment u kojem se više puta ponavlja... Da biste to izbjegli možete oblikujte ovaj isječak kao funkciju, a onda ga nazovi na pravim mjestima u kodu po imenu ove funkcije. Pozivanje ove funkcije značit će slijedeći upute nalazi u njemu.

Kako mogu organizirati izvršavanje nekog zadatka u JavaScriptu pomoću funkcija? Da bi to učinili, obično rade ovo:

  • razbiti zadatak na sastavne dijelove (podzadatke);
  • podzadaci su formalizirani kroz funkcije;
  • razviti glavni kod pomoću poziva generiranih funkcija.

Kao rezultat, takav program postaje strukturiraniji. Lakše je napraviti razne promjene i dodati nove značajke.

Deklaracija funkcije i poziv

Funkcijske operacije u JavaScriptu mogu se podijeliti u 2 koraka:

  • deklaracija (kreacija) funkcije.
  • pozivanje (izvršenje) ovu funkciju.

Deklaracija funkcije. Stvaranje funkcije u JavaScriptu počinje pisanjem ključne riječi funkcije, nakon čega slijedi naziv funkcije, a zatim u zagradama x, ako je potrebno. parametri su navedeni nakon čega slijede upute koje zatvorene su vitičastim zagradama.

// deklaracija funkcije someName funkcija someName () (upozorenje ("Pozvali ste funkciju someName!");) JavaScript - sintaksa deklaracije funkcije

Funkcije ove vrste u JavaScriptu se nazivaju izjava deklaracije funkcije... Osim ove vrste, JavaScript razlikuje i funkcije izraz definicije funkcije i izraz funkcije strelice.

Formiranje naziva funkcije slijedi ista pravila kao i naziv varijable. Oni. može sadržavati slova, brojeve (0-9), znakove "$" i "_". Preporuča se koristiti samo slova engleske abecede (a-z, A-Z) kao slova. Naziv funkcije, kao i naziv varijable, ne mogu početi znamenkom.

Funkcija može imati onoliko parametara koliko želite, ili uopće ne imati. Zagrade su u svakom slučaju naznačene. Ako postoji nekoliko parametara, onda se moraju međusobno odvojiti zarezom. Parametri funkcije adresiraju se svojim imenom.

Set uputa, zatvoren u vitičaste zagrade je kod funkcije koji će se izvršiti kada se pozove.

Poziv funkcije. Deklarirana funkcija svojom vlastitom neće biti izvršena... Da biste ga pokrenuli, morate ga nazvati. Funkcija se poziva navođenjem njenog imena i dvije zagrade. Argumenti su dati unutar zagrada, ako je potrebno.

// pozivamo funkciju danu u prethodnom primjeru someName (); JavaScript - Sintaksa poziva funkcije

Je li funkcija u JavaScriptu objekt?

Funkcije u JavaScriptu su objekti. U JavaScriptu je sve općenito objekt, osim šest primitivnih tipova podataka. A ako je funkcija objekt, onda se referenca na nju može spremiti u varijablu.

// deklaracija funkcije someName funkcija someName () (upozorenje ("Pozvali ste funkciju someName!");) var reference = someName;

Nakon toga, možete pozvati funkciju ovako:

Referenca ();

Parametri i argumenti funkcije

Argumenti funkcije- to su vrijednosti koje se prosljeđuju funkciji u fazi njenog poziva. Odvojite argumente jedan od drugog zarezom.

// pozvati funkciju sayWelcome s dva argumenta koja su joj proslijeđena sayWelcome ("Ivan", "Ivanov"); // drugi poziv funkciji sayWelcome s dva argumenta sayWelcome ("Petar", "Petrov");

Parametri funkcije Jedan je od načina u JavaScriptu na koji se možete pozivati ​​na argumente unutar funkcije. Parametri funkcije u fazi njezine deklaracije opisani su u zagradama.

Drugim riječima parametri funkcije- to su lokalne varijable koje se kreiraju automatski u fazi pokretanja funkcije. Kao vrijednosti, parametri primaju odgovarajuće argumente proslijeđene funkciji u vrijeme njezina poziva. Parametrima se može pristupiti samo unutar ove funkcije, izvan nje ne postoje.

// deklaracija funkcije sayWelcome, koja ima dva parametra funkciju sayWelcome (userFirstName, userLastName) (// instrukcija koja prikazuje vrijednosti parametara "userFirstName" i "userLastName" u konzoli console.log ("Welcome, " + userLastName + "" + userFirstName ;)

U JavaScriptu, prilikom pozivanja funkcije broj argumenata ne mora biti isti kao i broj parametara... Parametri koji nisu bili postavljeni na vrijednost prilikom poziva bit će nedefinirani.

Na primjer, pozovimo funkciju iz gornjeg primjera bez navođenja jednog ili dva parametra:

// pozvati funkciju sayWelcome i proslijediti joj jedan argument sayWelcome ("Peter"); // Welcome undefined Peter // pozovite sayWelcome funkciju bez prosljeđivanja argumenata sayWelcome (); // Dobrodošli, nedefinirano nedefinirano

Primjer funkcije koja će jednostavno ispisati argumente koji su joj proslijeđeni na konzolu preglednika:

// deklaracija funkcije funkcija outputParam (param1, param2, param3) (console.log (param1 + ";" + param2 + ";" + param3);) // poziva funkciju outputParam s različitim brojem parametara koji su joj proslijeđeni outputParam ("Kiša" , "Snijeg", "Magla"); // Kiša; Snijeg; Izlaz magleParam (17); // 17; nedefiniran; nedefiniran outputParam (24.33); // 24; 33; nedefiniran outputParam (); // nedefiniran; nedefiniran; nedefiniran

Drugi način upućivanja na argumente unutar funkcije je korištenje objekta posebnih argumenata. Argumentima se pristupa putem argumenata na isti način kao i elementima regularnog niza, tj. po njihovim serijskim brojevima. Dakle, argument je prvi argument, argumenti drugi i tako dalje.

// deklaracija funkcije zbroj funkcija zbroj (broj1, broj2) (/ * broj1 ili argumenti - dohvati vrijednost 1 argumenta num2 ili argumenata - dobije vrijednost argumenta 2 * / var sum1 = broj1 + broj2, sum2 = argumenti + argumenti; return "Zbroj, primljen na način 1 jednak je "+ sum1 +"; zbroj dobiven načinom 2 jednak je "+ sum2;) / * ispiši rezultat funkcije zbroja na konzolu 7 - prvi argument (možete referirajte ga i imenom num1 i korištenjem argumenata) 4 - drugi argument (možete ga pozvati i imenom num2 i pomoću argumenata) * / console.log (zbroj (7,4));

Glavna razlika između ovih metoda je u tome što vam prva od njih omogućuje pristup samo onim argumentima koji su imenovani u fazi deklaracije funkcije. Druga metoda vam omogućuje da dobijete vrijednost bilo kojeg argumenta, čak i ako nema naziv (po rednom broju). Ova značajka jezika JavaScript omogućuje vam stvaranje svestranih fleksibilnih funkcija.

Osim primanja argumenata, objekt arguments također vam daje do znanja koliko argumenata ima. To se radi pomoću svojstva duljine.

Iterirajte argumente proslijeđen funkciji, možete, na primjer, koristiti for ili for ... petlje.

// deklaracija funkcije zbroj funkcija sum () (var i = 0; console.log ("Izlaz svih argumenata pomoću petlje for"); for (i; i< arguments.length; i++) { console.log(i + 1 + " аргумент равен " + arguments[i]); } console.log("Вывод всех аргументов с помощью цикла for...of"); for (arg of arguments) { console.log(arg); } } // вызов функции sum sum(7, 4, 3, 1);

Funkcija koja ispisuje na konzolu sve argumente koji su joj proslijeđeni i njihov broj:

// funkcija deklaracije funkcije myFunction () (var i; console.log ("Broj proslijeđenih parametara =" + arguments.length); // ponovite sve parametre koristeći for petlju for (i = 0; i< arguments.length; i++) { console.log(i + " параметр = " + arguments[i]); } } // вызовы функции myFunction myFunction(3, 7, 27, "JavaScript"); myFunction(); myFunction("Яблоки", "Груши", "Апельсины");

Funkcija koja dodaje sve argumente koji su joj proslijeđeni (njihov broj nije unaprijed poznat):

// deklaracija funkcije var myCalc = function () (// ponavljanje svih parametara pomoću petlje for var i, sum = 0; for (i = 0; i lt; arguments.length; i ++) (zbroj + = argumenti [i] ;) // vrati zbroj kao rezultat vrati zbroj;) // pozovi funkciju (izlaz na konzolu) console.log (myCalc (4, 20, 17, -6));

Kao rezultat toga, pomoću objekta argumenata možete implementirati u tijelo funkcije:

  • provjera broja proslijeđenih argumenata;
  • koliko se parametara obrađuje.

Osim same funkcije, druge funkcije koje se nalaze u njoj također imaju pristup argumentima koji joj se prosljeđuju u fazi poziva.

Funkcija mainF (p1, p2) (funkcija childF () (console.log ("p1 =" + p1 + "; p2 =" + p2);) childF ();) mainF (3, 5); // p1 = 3; p2 = 5 mainF (4, 7); // p1 = 4; p2 = 7

Zadana vrijednost parametra

Od ECMAScript 2015 (6) parametar funkcije možete postaviti vrijednost koju će imati prema zadanim postavkama.

Na primjer, postavimo parametar "color" na njegovu zadanu vrijednost jednaku "# 009688":

Funkcija setBGColor (boja = "# 009688") (document.body.style.backgroundColor = boja;) setBGColor (); // boja pozadine bit će # 009688 setBGColor ("crvena"); // boja pozadine bit će crvena

Prije ECMAScript 2015, mogli ste postaviti parametar na zadanu vrijednost, na primjer, to je bilo ovako:

Funkcija setBGColor (boja) (boja = boja! == nedefinirano? Boja: "# 009688"; // postavite zadanu boju na "# 009688" document.body.style.backgroundColor = boja;)

Parametri mirovanja

Ako joj pri pozivanju funkcije proslijedite više argumenata nego što ima parametara, onda ostatak možete dobiti pomoću tzv. patametri odmora... Ova se značajka pojavila u jeziku od ECMAScript 2015.

// ... nums su preostali parametri, kojima se u ovom slučaju može pristupiti imenom nums funkcija doMath (mathAction, ... nums) (var rezultat = 0; nums.forEach (funkcija (vrijednost) (switch (mathAction) ) ( slučaj "sum": rezultat + = vrijednost; prekid; slučaj "sumCube": rezultat + = vrijednost ** 3; prekid; slučaj "sumSquare": rezultat + = vrijednost ** 2; prekid; zadano: rezultat = 0; )) ) vrati rezultat;) console.log (doMath ("zbroj", 3, 4, 21, -4)); // 24 (3 + 4 + 21 + (-4)) console.log (doMath ("sumSquare", 1, 4)); // 17 (1 ^ 2 + 4 ^ 2) console.log (doMath ("sumCube", 3, 2, 4)); // 99 (3 ^ 3 + 2 ^ 3 + 4 ^ 3)

Izjava o povratu

Naredba return namijenjena je vraćanju vrijednosti ili rezultata evaluacije izraza trenutne funkcije. Vrijednost ili izraz mora biti odvojen od povrata razmakom. Osim toga, naredba return prekida izvršavanje funkcije, t.j. sve upute koje slijede neće biti izvršene.

JavaScript funkcija uvijek vraća rezultat, bez obzira na to koristi li se izraz return ili ne.

// funkcija koja vraća rezultat funkcije sayWelcome (userFirstName, userLastName) (if ((! userFirstName) || (! userLastName)) vraća "Dobrodošao, anonimni korisnik"; inače vraća "Dobrodošli," + userLastName + "" + userFirstName ; ) // deklaracija varijable person var person; // dodijeli rezultat funkcije sayWelcome promjenljivoj osobi person = sayWelcome ("Ivan", "Ivanov"); // ispis vrijednosti varijable u konzolu console.log (person); // Uputa koja će ispisati na konzolu rezultat funkcije sayWelcome console.log (sayWelcome ("Petar", "Petrov")); // Uputa koja će ispisati na konzolu rezultat funkcije sayWelcome console.log (sayWelcome ("Sidorov")); JavaScript - Funkcija s provjerom parametara

JavaScript funkcija, kao rezultat svog izvođenja, uvijek vraća rezultat, čak i ako nije eksplicitno definiran pomoću izraza return. Ovaj rezultat je nedefiniran.

// 1. funkcija koja ne vraća nikakvu rezultatsku funkciju sayWelcome (userFirstName, userLastName) (console.log ("Welcome," + userLastName + "" + userFirstName);) // pokušajte dobiti rezultat iz funkcije koja to čini ne vraća ništa console .log (recimoDobrodošli ("Ivan", "Ivanov")); // 2. funkcija koja sadrži izraz return bez funkcije vrijednosti sayDay (dan) (dan = "Danas," + dan; return; // ovaj izraz neće biti izvršen jer dolazi nakon povratne izjave console.log ( dan) ;) // pokušati dobiti rezultat funkcije koja sadrži povratni izraz bez vrijednosti console.log (recimoDay ("21. veljače 2016.")); JavaScript - Dobijte vrijednost iz funkcije koja ništa ne vraća

Isti rezultat će se dobiti ako ne navedete povratnu vrijednost za izraz return.

Preopterećenje funkcije u JavaScriptu

Preopterećenje funkcija u programiranju je mogućnost deklariranja više funkcija s istim imenom u istom opsegu. Takve se funkcije međusobno razlikuju po vrsti i broju argumenata. Svaka funkcija ima svoju logiku programa. Preopterećenje funkcije koristi se tako da se slične radnje mogu izvesti pomoću jednog naziva funkcije.

JavaScript ne podržava preopterećenje funkcija kao što je, na primjer, u jezicima sličnim C. Oni. JavaScript ne može stvoriti više funkcija s istim imenom u istom opsegu.

Sličnu funkcionalnost moguće je implementirati u JavaScript pomoću sljedećih koraka:

  • Kako biste provjerili je li argument proslijeđen ili ne, upotrijebite uvjet s provjerom njegove vrijednosti za nedefinirano.
  • Koristite svojstvo duljine objekta da provjerite broj argumenata proslijeđenih funkciji.
  • Upotrijebite operatore typeof ili instanceof da biste saznali vrstu proslijeđene vrijednosti argumenta.
  • Za rad s promjenjivim brojem argumenata, koristite objekt arguments.
  • Počevši od ECMAScript6, možete dati zadane vrijednosti za argumente.

Na primjer, napravimo funkciju koja se može pozvati s jednim ili dva argumenta:

// deklaracija funkcije koja mijenja boju pozadine elemenata funkcija setBgColor (bgColor, elementi) (// ako parametar elemenata nije naveden prilikom pozivanja if (elementi === nedefinirano) (// zatim izjednačiti njegovu vrijednost "div" elementi = "div ";) // dohvati sve elemente elemente = $ (elementi); // iteriraj sve elemente i postavi ih na specificiranu boju pozadine elements.each (function () ($ (ovo) .css (" background -color", bgColor) ;));) / * Pozovite funkciju setBgColor s jednim parametrom. Jer 2 parametar nije naveden, tada će ova funkcija promijeniti boju pozadine svih div elemenata * / SetBgColor ("zeleno"); / * Pozovite funkciju setBgColor s 2 parametra. Jer 2 je naveden parametar, tada će ova funkcija promijeniti boju pozadine samo elemenata gumba * / SetBgColor ("# ff0000", "button");

Učinimo neke promjene u gornjem kodu. Naime, odredimo zadanu vrijednost za drugi parametar:

// deklariranje funkcije koja mijenja boju pozadine elemenata // parametar elemenata je postavljen na "div" prema zadanoj funkciji setBgColor (bgColor, elements = "div") (// dobiti sve elemente elemente = $ (elements); / / ponovite sve elemente i postavite ih na specificiranu boju pozadine elements.each (function () ($ (ova) .css ("background-color", bgColor);));) // pozovite funkciju setBgColor, navodeći jednu parametar setBgColor ("zeleno"); // pozivamo funkciju setBgColor, navodeći 2 parametra setBgColor ("# ff0000", "button");

Primjer kako u JavaScriptu možete implementirati "preopterećenu" funkciju koja izračunava broj kalorija koje osoba treba dnevno:

// opis funkcije funkcija countCal (spol, visina) (// parametri: spol (spol) i visina (visina) var rezultat; if ((sex === 0) || (sex === "muškarac")) ( rezultat = (visina - 100) * 20;) inače ako ((spol === 1) || (spol === "žena")) (rezultat = (visina - 105) * 19;) ako (rezultat) ( // argumenti - razina aktivnosti if (argumenti) (rezultat * = argumenti;) console.log ("Broj kcal za normalan život:" + rezultat);) else (console.log ("Navedeni su nevažeći parametri");) ) / * pozovite funkciju i proslijedite joj 2 argumenta (1 je "čovjek", može mu se pristupiti korištenjem naziva sex i argumenata; 2 je vrijednost 185, može se pristupiti pomoću imena sex i argumenata) * / countCal ("čovjek", 185); / * poziva funkciju i prosljeđuje joj 3 parametra, iako su u opisu funkcije samo 2 (u ovom slučaju vrijednost 3 parametra možete dobiti samo kao argumente) * / countCal (0, 185, 2);

Rekurzija

Rekurzija je poziv unutar tijela neke funkcije samoj sebi.

Poziv funkcije obično se provodi ovisno o tome kako je deklariran imenom ili putem varijable koja sadrži referencu na ovu funkciju.

Činjenica funkcije (n) (ako je (n === 1) (povratak 1;) povratna činjenica (n-1) * n;) console.log (činjenica (5)); // 120

Funkciju unutar njenog tijela možete pozvati ne samo imenom, već i korištenjem svojstva callee objekta argumenata. Ali bolje je ne koristiti ovo svojstvo, jer zastario je. Osim toga, u strogom načinu rada uopće ne radi.

Što su ugrađene (standardne) funkcije?

JavaScript ima ogroman skup ugrađenih (standardnih) funkcija. Ove su funkcije već opisane u samom motoru preglednika. Gotovo sve su metode objekta.

Na primjer, da biste pozvali ugrađenu funkciju (metodu) upozorenja, ne treba je deklarirati unaprijed. Već je opisano u pregledniku. Metoda upozorenja se poziva navođenjem imena, zagrada i argumenta unutar njih. Ova metoda je dizajnirana za prikaz poruke na ekranu u obliku dijaloškog okvira. Tekstualna poruka se preuzima iz vrijednosti parametra ove funkcije.

// pozivanje funkcije alert alert ("Neki tekst"); JavaScript - Pozivanje funkcije upozorenja

Funkcije su jedan od temeljnih građevnih blokova u JavaScriptu. Funkcija je JavaScript procedura-skup iskaza koji izvršava zadatak ili izračunava vrijednost. Da biste koristili funkciju, morate je definirati negdje u opsegu iz kojeg je želite pozvati.

A metoda je funkcija koja je svojstvo objekta. Više o objektima i metodama pročitajte u Rad s objektima.

Funkcije poziva

Definiranje funkcije ne izvršava je. Definiranje funkcije jednostavno imenuje funkciju i specificira što učiniti kada se funkcija pozove. Zove funkcija zapravo izvodi navedene radnje s naznačenim parametrima. Na primjer, ako definirate kvadrat funkcije, možete ga nazvati na sljedeći način:

Kvadrat (5);

Prethodni izraz poziva funkciju s argumentom 5. Funkcija izvršava svoje naredbe i vraća vrijednost 25.

Funkcije moraju biti u opsegu kada su pozvane, ali deklaracija funkcije može biti podignuta (pojavljuje se ispod poziva u kodu), kao u ovom primjeru:

Console.log (kvadrat (5)); / * ... * / kvadrat funkcije (n) (povratak n * n;)

Opseg funkcije je funkcija u kojoj je deklarirana ili cijeli program ako je deklarirana na najvišoj razini.

Bilješka: Ovo funkcionira samo kada definirate funkciju koristeći gornju sintaksu (tj. FuncName () ()). Kod u nastavku neće raditi. To znači da podizanje funkcije radi samo s deklaracijom funkcije, a ne s izrazom funkcije.

Console.log (kvadrat); // trg je podignut s nedefiniranom početnom vrijednošću. console.log (kvadrat (5)); // TypeError: square nije funkcija var square = function (n) (vrat n * n;)

Argumenti funkcije nisu ograničeni na nizove i brojeve. Možete proslijediti cijele objekte funkciji. Funkcija show_props () (definirana u) je primjer funkcije koja uzima objekt kao argument.

Funkcija može pozvati samu sebe. Na primjer, evo funkcije koja rekurzivno izračunava faktorijale:

Faktorijal funkcije (n) (ako ((n === 0) || (n === 1)) vrati 1; inače vrati (n * faktorijel (n - 1));)

Tada biste mogli izračunati faktorijele od jedan do pet na sljedeći način:

Var a, b, c, d, e; a = faktorijel (1); // a dobiva vrijednost 1 b = faktorijel (2); // b dobiva vrijednost 2 c = faktorijel (3); // c dobiva vrijednost 6 d = faktorijel (4); // d dobiva vrijednost 24 e = faktorijel (5); // e dobiva vrijednost 120

Postoje i drugi načini pozivanja funkcija. Često postoje slučajevi u kojima se funkcija mora pozvati dinamički, ili se broj argumenata funkcije razlikuje, ili u kojima se kontekst poziva funkcije treba postaviti na određeni objekt određen tijekom izvođenja. Ispada da su funkcije same po sebi objekti, a ti objekti zauzvrat imaju metode (vidi objekt Funkcija). Jedna od njih, metoda primjene (), može se koristiti za postizanje ovog cilja.

Opseg funkcije

Varijablama definiranim unutar funkcije ne može se pristupiti nigdje izvan funkcije, jer je varijabla definirana samo u opsegu funkcije. Međutim, funkcija može pristupiti svim varijablama i funkcijama definiranim unutar opsega u kojem je definirana. Drugim riječima, funkcija definirana u globalnom opsegu može pristupiti svim varijablama definiranim u globalnom opsegu. Funkcija definirana unutar druge funkcije također može pristupiti svim varijablama definiranim u svojoj roditeljskoj funkciji i bilo kojoj drugoj varijabli kojoj roditeljska funkcija ima pristup.

// Sljedeće varijable definirane su u globalnom opsegu var num1 = 20, num2 = 3, name = "Chamahk"; // Ova je funkcija definirana u funkciji globalnog opsega multiply () (povratak num1 * num2;) multiply (); // Vraća 60 // Primjer funkcije ugniježđene funkcije getScore () (var num1 = 2, num2 = 3; funkcija add () (povratni naziv + "score" + (num1 + num2);) return add ();) getScore (); // Vraća "Chamahk zabio 5"

Opseg i stog funkcija

Rekurzija

Funkcija se može pozivati ​​i pozivati ​​samu sebe. Postoje tri načina da se funkcija referira na sebe:

  1. naziv funkcije
  2. varijabla u opsegu koja se odnosi na funkciju

Na primjer, razmotrite sljedeću definiciju funkcije:

Var foo = funkcijska traka () (// izjave idu ovdje);

Unutar tijela funkcije, sljedeće su sve ekvivalentne:

  1. traka ()
  2. arguments.callee ()
  3. foo ()

Funkcija koja sama sebe poziva zove se a rekurzivna funkcija... Na neki način, rekurzija je analogna petlji. Oba izvršavaju isti kod više puta, a oba zahtijevaju uvjet (kako bi se izbjegla beskonačna petlja, odnosno beskonačna rekurzija u ovom slučaju). Na primjer, sljedeća petlja:

Var x = 0; dok (x< 10) { // "x < 10" is the loop condition // do stuff x++; }

može se pretvoriti u rekurzivnu funkciju i poziv toj funkciji:

Petlja funkcije (x) (ako je (x> = 10) // "x> = 10" je izlazni uvjet (ekvivalentno "! (X< 10)") return; // do stuff loop(x + 1); // the recursive call } loop(0);

Međutim, neki algoritmi ne mogu biti jednostavne iterativne petlje. Na primjer, dobivanje svih čvorova strukture stabla (npr. DOM-a) lakše je izvesti pomoću rekurzije:

Funkcija walkTree (čvor) (if (čvor == null) // return; // učinite nešto s čvorom za (var i = 0; i< node.childNodes.length; i++) { walkTree(node.childNodes[i]); } }

U usporedbi s petljom funkcije, svaki rekurzivni poziv sam po sebi čini mnogo rekurzivnih poziva ovdje.

Moguće je pretvoriti bilo koji rekurzivni algoritam u nerekurzivni, ali često je logika mnogo složenija i za to je potrebna uporaba steka. Zapravo, sama rekurzija koristi stog: stog funkcija.

Ponašanje poput steka može se vidjeti u sljedećem primjeru:

Funkcija foo (i) (ako (i< 0) return; console.log("begin: " + i); foo(i - 1); console.log("end: " + i); } foo(3); // Output: // begin: 3 // begin: 2 // begin: 1 // begin: 0 // end: 0 // end: 1 // end: 2 // end: 3

Ugniježđene funkcije i zatvaranja

Funkciju možete ugnijezditi unutar funkcije. Ugniježđena (unutarnja) funkcija privatna je za svoju (vanjsku) funkciju. Također tvori a zatvaranje... Zatvaranje je izraz (obično funkcija) koji može imati slobodne varijable zajedno s okruženjem koje veže te varijable (koje "zatvara" izraz).

Budući da je ugniježđena funkcija zatvaranje, to znači da ugniježđena funkcija može "naslijediti" argumente i varijable svoje funkcije koja sadrži. Drugim riječima, unutarnja funkcija sadrži opseg vanjske funkcije.

  • Unutarnjoj funkciji može se pristupiti samo iz izraza vanjske funkcije.
  • Unutarnja funkcija tvori zatvaranje: unutarnja funkcija može koristiti argumente i varijable vanjske funkcije, dok vanjska funkcija ne može koristiti argumente i varijable unutarnje funkcije.

Sljedeći primjer prikazuje ugniježđene funkcije:

Funkcija addSquares (a, b) (funkcija kvadrat (x) (povrat x * x;) povratak kvadrat (a) + kvadrat (b);) a = addSquares (2, 3); // vraća 13 b = addSquares (3, 4); // vraća 25 c = addSquares (4, 5); // vraća 41

Budući da unutarnja funkcija čini zatvaranje, možete pozvati vanjsku funkciju i odrediti argumente za vanjsku i unutarnju funkciju:

Funkcija izvan (x) (funkcija unutar (y) (povratak x + y;) povratak unutra;) fn_inside = izvan (3); // Razmislite o tome kao: dajte mi funkciju koja dodaje 3 svemu što date // it result = fn_inside (5); // vraća 8 rezultat1 = izvan (3) (5); // vraća 8

Očuvanje varijabli

Primijetite kako se x čuva kada se vrati unutra. Zatvaranje mora sačuvati argumente i varijable u svim opsegima na koje upućuje. Budući da svaki poziv pruža potencijalno različite argumente, kreira se novo zatvaranje za svaki poziv prema van. Memorija se može osloboditi tek kada vraćena unutra više nije dostupna.

Ovo se ne razlikuje od pohranjivanja referenci u druge objekte, ali je često manje očito jer se reference ne postavljaju izravno i ne mogu ih pregledati.

Višestruko ugniježđene funkcije

Funkcije mogu biti višestruko ugniježđene, tj. funkcija (A) koja sadrži funkciju (B) koja sadrži funkciju (C). Obje funkcije B i C formiraju zatvaranja ovdje, tako da B može pristupiti A i C može pristupiti B. Osim toga, budući da C može pristupiti B koji može pristupiti A, C također može pristupiti A. Dakle, zatvaranja mogu sadržavati višestruke opsege; oni rekurzivno sadrže opseg funkcija koje ga sadrže. Ovo se zove ulančavanje opsega... (Zašto se to zove "ulančavanje" bit će objašnjeno kasnije.)

Razmotrimo sljedeći primjer:

Funkcija A (x) (funkcija B (y) (funkcija C (z) (konzola.log (x + y + z);) C (3);) B (2);) A (1); // zapisi 6 (1 + 2 + 3)

U ovom primjeru, C pristupa B "s y i A" s x. To se može učiniti jer:

  1. B tvori zatvaranje uključujući A, t.j. B može pristupiti A-ovim argumentima i varijablama.
  2. C čini zatvaranje uključujući B.
  3. Budući da B-ovo zatvaranje uključuje A, C-ovo zatvaranje uključuje A, C može pristupiti oba B i Argumenti i varijable A. Drugim riječima, C lanci opsege B i A tim redoslijedom.

Obrnuto, međutim, nije istina. A ne može pristupiti C, jer A ne može pristupiti nijednom argumentu ili varijabli B, čija je C varijabla. Dakle, C ostaje privatan samo za B.

Sukobi imena

Kada dva argumenta ili varijable u opsegu zatvaranja imaju isto ime, postoji a sukob imena... Više unutarnjih opsega ima prednost, tako da najveći unutarnji opseg ima najveći prioritet, dok najudaljeniji opseg ima najniži. Ovo je lanac opsega. Prvi na lancu je najunutarnjiji opseg, a posljednji je najudaljeniji opseg. Uzmite u obzir sljedeće:

Funkcija izvan () (var x = 5; funkcija unutar (x) (povrat x * 2;) povratak unutra;) izvan () (10); // vraća 20 umjesto 10

Sukob imena događa se u naredbi return x i nalazi se između unutarnjeg parametra x i van varijable x. Lanac opsega je ovdje (unutar, izvan, globalni objekt). Stoga unutar "s x ima prednost nad vanjskim" s x, a 20 (unutar "s x) se vraća umjesto 10 (izvan" s x).

Zatvaranja

Zatvaranja su jedna od najmoćnijih značajki JavaScripta. JavaScript dopušta ugniježđenje funkcija i daje unutarnjoj funkciji potpuni pristup svim varijablama i funkcijama definiranim unutar vanjske funkcije (i svim ostalim varijablama i funkcijama kojima vanjska funkcija ima pristup). Međutim, vanjska funkcija nema pristup varijablama i funkcijama definiranim unutar unutarnje funkcije. To osigurava svojevrsnu enkapsulaciju za varijable unutarnje funkcije. Također, budući da unutarnja funkcija ima pristup opsegu vanjske funkcije, varijable i funkcije definirane u vanjskoj funkciji živjet će dulje od trajanja izvršenja vanjske funkcije, ako unutarnja funkcija uspije preživjeti izvan vijeka trajanja vanjske funkcije. funkcija. Zatvaranje se stvara kada je unutarnja funkcija na neki način dostupna bilo kojem opsegu izvan vanjske funkcije.

Var pet = funkcija (ime) (// Vanjska funkcija definira varijablu pod nazivom "name" var getName = function () (povratno ime; // Unutarnja funkcija ima pristup varijabli "name" vanjske // funkcije) return getName; // Vraća unutarnju funkciju, izlažući je na taj način vanjskim opsegima) myPet = pet ("Vivie"); moj ljubimac (); // Vraća "Vivie"

Može biti puno složeniji od gornjeg koda. Objekt koji sadrži metode za manipuliranje unutarnjim varijablama vanjske funkcije može se vratiti.

Var createPet = funkcija (ime) (var spol; povratak (setName: funkcija (novoName) (name = newName;), getName: funkcija () (povratni naziv;), getSex: funkcija () (povratni spol;), setSex: funkcija (newSex) (if (typeof newSex === "string" && (newSex.toLowerCase () === "muški" || newSex.toLowerCase () === "žensko")) (sex = newSex;)) )) var pet = createPet ("Vivie"); pet.getName (); // Vivie pet.setName ("Oliver"); pet.setSex ("muško"); pet.getSex (); // muški ljubimac.getName (); // Oliver

U gornjem kodu, varijabla imena vanjske funkcije dostupna je unutarnjim funkcijama i ne postoji drugi način za pristup unutarnjim varijablama osim kroz unutarnje funkcije. Unutarnje varijable unutarnjih funkcija djeluju kao sigurna pohrana za vanjske argumente i varijable. Sadrže "trajne" i "inkapsulirane" podatke za rad s unutarnjim funkcijama. Funkcije čak ne moraju biti dodijeljene varijabli ili imaju ime.

Var getCode = (funkcija () (var apiCode = "0] Eal (eh & 2"; // Kod koji ne želimo da autsajderi mogu mijenjati ... return function () (return apiCode;);)) () ; getCode (); // Vraća apiCode

Međutim, postoji niz zamki na koje treba paziti pri korištenju zatvarača. Ako zatvorena funkcija definira varijablu s istim imenom kao i naziv varijable u vanjskom opsegu, ne postoji način da se ponovno uputi na varijablu u vanjskom opsegu.

Var createPet = function (name) (// Vanjska funkcija definira varijablu pod nazivom "name". Povrat (setName: function (name)) (// Priložena funkcija također definira varijablu pod nazivom "name". Name = name; // Kako pristupiti "nazivu" definiranom vanjskom funkcijom?)))

Korištenje objekta arguments

Argumenti funkcije održavaju se u objektu nalik nizu. Unutar funkcije možete adresirati argumente koji su joj proslijeđeni na sljedeći način:

Argumenti [i]

gdje je i redni broj argumenta, počevši od nule. Dakle, prvi argument proslijeđen funkciji bi bili argumenti. Ukupan broj argumenata označen je argumentima.dužina.

Koristeći objekt arguments, možete pozvati funkciju s više argumenata nego što je formalno deklarirano da prihvaća. Ovo je često korisno ako ne znate unaprijed koliko će argumenata biti proslijeđeno funkciji. Možete koristiti arguments.length da odredite broj argumenata koji su stvarno proslijeđeni funkciji, a zatim pristupite svakom argumentu pomoću objekta arguments.

Na primjer, razmotrite funkciju koja spaja nekoliko nizova. Jedini formalni argument za funkciju je niz koji specificira znakove koji razdvajaju stavke za spajanje. Funkcija je definirana kako slijedi:

Funkcija myConcat (separator) (var result = ""; // inicijaliziranje popisa var i; // ponavljanje kroz argumente za (i = 1; i< arguments.length; i++) { result += arguments[i] + separator; } return result; }

Možete proslijediti bilo koji broj argumenata ovoj funkciji, a ona spaja svaki argument u niz "list":

// vraća "crveno, narančasto, plavo," myConcat (",", "crveno", "narančasto", "plavo"); // vraća "slon; žirafa; lav; gepard;" myConcat (";", "slon", "žirafa", "lav", "gepard"); // vraća "kadulja. bosiljak. origano. papar. peršin." myConcat (".", "kadulja", "bosiljak", "origano", "papar", "peršin");

Bilješka: Varijabla argumenata je "slična nizu", ali nije niz. Sličan je nizu po tome što ima numerirani indeks i svojstvo duljine. Međutim, ne posjeduje sve metode manipulacije nizom.

Na uvođenje funkcija strelica utjecala su dva čimbenika: kraće funkcije i njihovo neobvezivanje.

Kraće funkcije

U nekim funkcionalnim obrascima kraće funkcije su dobrodošle. usporedi:

Var a = ["Vodik", "Helij", "Litij", "Berilij"]; var a2 = a.map (funkcija (s) (povrat s.length;)); console.log (a2); // zapisi var a3 = a.map (s => s.length); console.log (a3); // dnevnici

Nema ovo odvojeno

Sve do funkcija strelice, svaka nova funkcija definirala je vlastitu vrijednost (novi objekt u slučaju konstruktora, nedefiniran u pozivima funkcije, osnovni objekt ako se funkcija poziva kao "metoda objekta" itd.). To se pokazalo manje nego idealnim s objektno orijentiranim stilom programiranja.

Funkcija Person () (// Konstruktor Person () definira `this` kao sebe.this.age = 0; setInterval (funkcija growUp () (// U nestriktnom načinu rada, growUp () funkcija definira` this` // kao globalni objekt, koji se razlikuje od `this` // definiranog od strane osobe () constructor.this.age ++;), 1000);) var p = nova osoba ();

U ECMAScript 3/5, ovaj problem je riješen dodjeljivanjem vrijednosti u ovoj varijabli koja se može zatvoriti.

Funkcija Osoba () (var self = this; // Neki biraju `to` umjesto` self`. // Odaberite jednu i budite dosljedni.self.age = 0; setInterval (funkcija growUp () (// Povratni poziv se odnosi na varijabla `self` čija je // vrijednost očekivani object.self.age ++;), 1000);)

Svaki programer dobro zna što su funkcije i zašto su potrebne. Međutim, funkcije u Javascriptu imaju nekoliko čuda. Ako već dugo programirate na ovom jeziku, vjerojatno znate da postoje različiti. Ako dolazite s drugog jezika, onda ste čitajući neke od članaka najvjerojatnije vidjeli ovu, na prvi pogled, čudnu deklaraciju funkcije:

Var add = funkcija (arg1, arg2) (var zbroj = arg1 + arg2; povratni zbroj;) var rezultat = add (5, 2); // rezultat je sada 7

To jest, funkcija, prije svega, nema ime. Drugo, on je dodijeljen varijabli, ali ne samo dodijeljen, već njezino tijelo odmah ide. Osobno, kod mene, koji sam prije pisao na jezicima kao što su VB, C++, takva je izjava izazvala zbunjenost i nerazumijevanje kako funkcionira i zašto je uopće tako pisati.

Navikao sam na deklaraciju i poziv "klasične" funkcije, ovako:

Funkcija add (arg1, arg2) (var zbroj = arg1 + arg2; povratni zbroj;) var rezultat = add (5, 3); // rezultat je sada 8

I tu dolazimo do posebnosti funkcija u Javascriptu. Radi lakšeg razumijevanja, zamislite da je funkcija u JS-u obična vrijednost, kao što je broj ili niz. Možete li upisati broj 5 u varijablu rezultata? Ili nešto složenije, poput niza, a zatim ga prikazati na ekranu? Možeš. Dakle, ako zamislimo da je funkcija obična vrijednost, iako vrlo složena struktura, tada se prvi način njezinog deklariranja više ne čini nevjerojatnim.

Sljedeća zanimljivost je logičan nastavak prve. Nakon što stavimo podatke u varijablu, možemo ih prenijeti u drugu varijablu kroz naziv ove varijable:

Var a = 5; var b = a; uzbuna (b); // će ispisati 5

Uobičajena stvar. Sada pogledajte ovaj kod:

Var add = funkcija (arg1, arg2) (var zbroj = arg1 + arg2; povratni zbroj;) var calcSum = add; upozorenje (calcSum (5, 6)); // ispisuje 11

Već počinjete nagađati? Budući da je funkcija poput varijable, možemo je "umnožiti" uobičajenim dodjeljivanjem u druge varijable, pretvarajući ih također u funkcije. Sada calcSum može dodati i dva broja. Međutim, kod

Var calcSum = dodaj (1, 1); // calcSum je sada jednak 2, ovo nije funkcija, već varijabla s upozorenjem o broju (calcSum (5, 6)); //pogreška

Neće se izvršiti, jer u prvom retku nismo dodijelili samu funkciju, već rezultat njenog izvršenja (zagrade označavaju da trebamo izvršiti funkciju, a ne dodijeliti je).

Ako trebate pozvati funkciju samu, to se radi na sljedeći način:

Var calcFact = funkcija fact (val) (if (val == 1)? Val: val * fact (val - 1); // izračunavanje faktorijala pomoću rekurzije) alert (calcFact (4)); // tiska 24

Ovdje, dodjeljivanjem funkcije varijabli, dali smo joj ime fact. Međutim, ovaj će naziv biti dostupan samo unutar same funkcije i nigdje drugdje. Razlozi za to leže u principu tumača i izvan su okvira lekcije.

Možda se pitate: "Hm, zanimljiva prilika! Ali koja je prednost ove metode? Postoje li situacije kada se ne može bez nje ili je barem prikladnija od običnog oglasa?" Neću tvrditi da postoje situacije u kojima se takav pristup ne može izostaviti, ali mogu navesti primjer gdje se smanjuje količina koda. Recimo da trebate pozdraviti osobu ovisno o dobu dana:

Var datum = novi datum (); var hello = (date.getHours ()< 12) ? function() {alert("Доброе утро!")} : (date.getHours() < 18) ? function() {alert("Добрый день!")} : function() {alert("Добрый вечер!")}; hello();

Kao što možete vidjeti, funkcije su iznimno jednostavne, s jednom naredbom za upozorenje.

Ako bismo odlučili ići na "klasičan način", onda bismo morali napisati tri odvojene funkcije, a zatim ih pozvati u uvjetu provjere vremena:

Funkcija goodMorning () (upozorenje ("Dobro jutro!");) Funkcija goodAfternoon () (upozorenje ("Dobar dan!");) Funkcija goodEvning () (upozorenje ("Dobra večer!");) Var date = novi datum (); (datum.getHours ()< 12) ? goodMorning() : (date.getHours() < 18) ? goodAfternoon() : goodEvning();

Kod je vizualno značajno narastao, čak i s obzirom na to da smo koristili kratki oblik zapisa za uvjetni operator. Ako pretpostavimo da datoteka sadrži stvarno važne funkcije koje izvode izračune, onda pretrpavanje popisa takvim mini funkcijama koje nemaju važnu logiku, a koje se koriste, najvjerojatnije, samo jednom, nije dobra ideja. Osim toga, prisiljeni smo svakoj funkciji dati jedinstveno ime i naznačiti ga prilikom poziva. Stoga, ako trebate promijeniti ime jednog od njih, morat ćete ga promijeniti na dva mjesta, što povećava vjerojatnost pogreške.

Drugo, ako koristimo "klasičnu" metodu, tada gubimo mogućnost dodjeljivanja funkcije varijabli. Odnosno, napišite

Funkcija add (a, b) (vraćanje a + b;) var calcSum = add; calcSum (5, 5);

To više nije moguće. Stoga, u našem primjeru, ako još uvijek trebamo pozdraviti gosta više puta, morat ćemo svaki put duplicirati ovaj fragment:

(datum.getHours ()< 12) ? goodMorning() : (date.getHours() < 18) ? goodAfternoon() : goodEvning();

A u prvom slučaju bit će dovoljno samo napisati pozdrav (); a rezultat će biti isti.

Rekao sam vam o zanimljivoj značajci JS funkcija i dao primjere. Dakle, vidjeli ste to načine pozivanja funkcija u Javascriptu nisu ograničeni samo na jednu vrstu. Čak i ako ne možete odmah pronaći primjenu za te mogućnosti u svojim projektima, barem ćete znati da takve mogućnosti postoje. A kada dođe prava sreća, možete smanjiti količinu koda i izbjeći nepotrebnu zbrku i pogreške!

Ovaj članak opisuje funkcije na razini jezika Javascript: stvaranje, parametre, trikove, zatvaranja i još mnogo toga.

Stvaranje funkcija

Postoje 3 načina za stvaranje funkcije. Glavna razlika kao rezultat njihovog rada je ta što je imenovana funkcija vidljiva posvuda, a anonimna tek nakon deklaracije:

Funkcije – objekti

U javascriptu funkcije su punopravni objekti ugrađene klase Function. Zato se mogu dodijeliti varijablama, proslijediti i, naravno, imaju svojstva:

Funkcija f () (...) f.test = 6 ... upozorenje (f.test) // 6

Svojstva funkcije također su dostupna unutar funkcije, tako da se mogu koristiti kao statičke varijable.

Na primjer,

Funkcija func () (var funcObj = arguments.callee funcObj.test ++ upozorenje (funcObj.test)) func.test = 1 funkcija () func ()

Na početku, svaka funkcija stvara varijablu argumenata unutar sebe i dodjeljuje arguments.callee referencu sebi. Dakle arguments.callee.test je svojstvo func.test, tj. test statičke varijable.

U primjeru se dodjela nije mogla izvršiti:

Var test = arguments.callee.test test ++

budući da bi u ovom slučaju operacija ++ radila na testu lokalne varijable, a ne na svojstvu testa funkcijskog objekta.

Objekt arguments također sadrži sve argumente i može se pretvoriti u niz (iako nije), pogledajte dolje u odjeljku o parametrima.

Opsegovi

Svaka funkcija, ili bolje rečeno, svako pokretanje funkcije, postavlja vlastiti individualni opseg.

Varijable se mogu deklarirati bilo gdje. Ključna riječ var postavlja varijablu u trenutnom opsegu. Ako ga zaboravite, varijabla će otići na globalni objekt prozora. Moguća su neočekivana križanja s drugim varijablama prozora, sukobi i kvarovi.

Za razliku od brojnih jezika, blokovi ne definiraju poseban opseg. Nema razlike je li varijabla definirana unutar bloka ili izvan njega. Dakle, ova dva isječka su savršeno ekvivalentna:

Varijabla navedena putem var vidljiva je posvuda u opsegu, čak i prije naredbe var. Na primjer, napravimo funkciju koja će promijeniti varijablu, var za koju se nalazi ispod.

Na primjer:

Funkcija a () (z = 5 // promijeniti z lokalno .. // .. jer je z deklariran putem var var z) // test delete z // brisanje globalnog za () upozorenje za svaki slučaj (window.z) // => nedefinirano jer je z promijenjen lokalno

Parametri funkcije

Funkcije se mogu izvoditi s bilo kojim brojem parametara.

Ako se funkciji prosljeđuje manje parametara nego što ih ima u definiciji, oni koji nedostaju smatraju se nedefiniranima.

Sljedeća funkcija vraća vrijeme potrebno za prelazak udaljenosti s ravnomjernom brzinom.

Prilikom prvog pokretanja, funkcija radi s argumentima udaljenost = 10, brzina = nedefinirano. Obično ova situacija, ako je podržana od strane funkcije, daje zadanu vrijednost:

// ako je brzina lažna vrijednost (nedefinirano, 0, lažno ...) - zamijenite 10 brzina = brzina || 10

Operater || u javascriptu ne vraća true / false, već samu vrijednost (prvu, koja se pretvara u true).

Stoga se koristi za postavljanje zadanih vrijednosti. U našem pozivu brzina će biti nedefinirana || 10 = 10.

Dakle, rezultat će biti 10/10 = 1.

Drugo lansiranje je standardno.

Treći niz daje nekoliko dodatnih argumenata. Funkcija ne predviđa rad s dodatnim argumentima, pa se oni jednostavno zanemaruju.

Pa, u potonjem slučaju uopće nema argumenata, pa je udaljenost = nedefinirana, a rezultat dijeljenja je nedefiniran / 10 = NaN (Nije-A-Broj, došlo je do pogreške).

Rad s neograničenim brojem parametara

Neposredno prije ulaska u tijelo funkcije automatski se kreira objekt argumenata koji sadrži

  1. Argumenti poziva koji počinju od nule
  2. Duljina u svojstvu duljine
  3. Referenca na samu funkciju u svojstvu pozivatelja

Na primjer,

Funkcija func () (za (var i = 0; i

Svojstvo arguments je poput niza po tome što ima duljinu i numeričke indekse. Zapravo, argumenti ne pripadaju klasi Array i ne sadrže njezine metode kao što su push, pop i druge.

Ako i dalje želite koristiti ove metode, na primjer, za pozivanje druge funkcije s istim argumentima, ali osim prve, možete stvoriti pravi niz od argumenata:

Var args = Array.prototype.slice.call (arguments) // .. sada je args pravi niz argumenata .. args.shift () ...

Možete pozvati funkciju na nizu argumenata koristeći apply:

Var func = funkcija (a, b) (upozorenje (a + b)) var arr = func.apply (null, arr) // => upozorenje (3)

Primjer prosljeđivanja funkcije referencom

Funkcija se lako može proslijediti kao argument drugoj funkciji.

Na primjer, map uzima funkciju func, primjenjuje je na svaki element u nizu arr i vraća rezultirajući niz:

Var map = funkcija (func, arr) (var rezultat = za (var i = 0; i

Primjer upotrebe:

Karta (trčanje,) // =

Ili možete stvoriti anonimnu funkciju izravno u pozivu mape:

// anonimna funkcija utrostručuje mapu brojeva (funkcija (a) (vrati a * 3),) // =

Preklapanje parametara u objekt

Postoje funkcije čiji se argumenti jako razlikuju.

Na primjer:

// možete navesti samo dio argumenata // nije navedeno - izračunavaju se ili uzimaju prema zadanoj funkciji promjene veličine (toWidth, toHeight, saveProportions, animate) (// zadane vrijednosti saveProportions = saveProportions || true animate = animate | | true toHeight = toHeight | | ...)

Poziv s izbornim parametrima mora se izvesti ovako:

Promjena veličine (100, null, null, istina)

Kako biste izbjegli nepotrebne nulte vrijednosti i učinili kod čitljivijim, koristite nešto poput "argumenata ključnih riječi" koji postoje u Pythonu i Rubyju. Za to su mnogi parametri pakirani u jedan objekt:

Promjena veličine funkcije (postavka) (// zadane vrijednosti var saveProportions = setup.saveProportions || true var animate = setup.animate || true var toHeight = setup.toHeight || ...)

Poziv je sada puno lakši:

Var setup = (toWidth: 100, animate: true) resize (setup) // ili resize (toWidth: 100, animate: true))

Dakle - puno jasnije. A ako postoji više od 5 parametara, onda općenito - jedini normalan način.

Osim toga, prikladnije je napraviti niz poziva s objektom kao što je:

Var setup = (toWidth: 100, animate: true, saveProportions: false) resize (setup) setup.toWidth = 200 resize (setup)

Vrhunski povezani članci