Kako podesiti pametne telefone i računare. Informativni portal
  • Dom
  • OS
  • Funkcionalno programiranje. Funkcije u JavaScript-u

Funkcionalno programiranje. Funkcije u JavaScript-u

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 sa konceptom funkcije pod drugim imenom, kao što je potprogram ili procedura. Funkcije mogu imati parametre: Definicija funkcije može uključivati ​​listu 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 izračunavanje povratne vrijednosti, koja je vrijednost izraza poziva funkcije. Pored argumenata, prilikom pozivanja bilo koje funkcije, prosljeđuje se još jedna vrijednost koja određuje kontekst poziva - vrijednost u ključnoj riječi ovo.

Funkcije u JavaScript-u su objekti i mogu se koristiti na različite načine. Na primjer, funkcije se mogu dodijeliti varijablama i proslijediti drugim funkcijama. Budući da su funkcije objekti, možete dodijeliti vrijednosti njihovim svojstvima, pa čak i pozvati njihove metode.

JavaScript dozvoljava da definicije funkcija budu ugniježđene unutar drugih funkcija, a takve funkcije će imati pristup svim varijablama prisutnim u opsegu definicije.

Definiranje funkcija

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

Identifikator koji specificira ime funkcije

Ime je obavezan dio izraza deklaracije funkcije: koristit će se za kreiranje nove varijable kojoj će biti dodijeljen novi objekt funkcije. U izrazima definicije funkcije ime može biti odsutno: ako je prisutno, ime će se odnositi na objekt funkcije samo u tijelu same funkcije.

Par zagrada oko liste sa nula ili više identifikatora, odvojenih zarezima

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

Par vitičastih zagrada sa nula ili više JavaScript instrukcija unutra

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

Sljedeći primjer pokazuje nekoliko definicija funkcija u obliku naredbi i izraza. Imajte na umu da su definicije funkcija kao izrazi korisne samo ako su dio većih izraza, kao što je dodjela ili poziv funkcije, koji rade nešto s novo deklariranom funkcijom:

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

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

S druge strane, izraz definicije funkcije ne deklarira varijablu. Međutim, u definicijskim izrazima moguće je specificirati ime funkcije, kao u gornjoj faktorskoj funkciji, koja može biti potrebna u tijelu funkcije da bi se sama pozvala. Ako izraz definicije funkcije uključuje ime, to ime će se odnositi na objekt funkcije u opsegu te funkcije. U stvari, ime funkcije postaje lokalna varijabla, dostupna samo u tijelu funkcije. U većini slučajeva, naziv funkcije ne mora biti specificiran 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 funkciju 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 naredbe return, tumač će jednostavno izvršiti sve naredbe u tijelu funkcije i vratiti nedefinirano u program koji poziva.

Većina funkcija u primjeru daje neku vrijednost i koristi naredbu return da vrati tu vrijednost u program koji poziva. Funkcija printprops() je malo drugačija u tom smislu: njen posao je da ispiše imena svojstava objekta. Ne mora vratiti nikakvu vrijednost, tako da u funkciji ne postoji izraz return. Funkcija printprops() će uvijek vratiti nedefinirano. (Funkcije koje nemaju povratnu vrijednost ponekad se nazivaju procedurama.)

Funkcije poziva

Programski kod koji formira tijelo funkcije se ne izvršava u trenutku kada je funkcija definirana, već u trenutku kada je pozvana. Pozivi funkcija se vrše pomoću izraza poziva. Izraz poziva sastoji se od izraza za poziv funkcije koji vraća funkcijski objekt, nakon čega slijede zagrade s popisom razdvojenih zarezima sa nula ili više izraza argumenata.

Ako je izraz poziva funkcije izraz poziva svojstva - ako je funkcija svojstvo objekta ili element niza (tj. metoda) - onda je izraz poziva izraz poziva metode. Sljedeći isječak prikazuje nekoliko primjera uobičajenih izraza poziva funkcije:

Printprops((x:4, starost: 24)); var d = udaljenost (1,1,5,6); var f = faktorijel(5) / faktorijel(12); f = kvadrat(5);

Kada se pozove funkcija, procjenjuju se svi izrazi argumenata (navedeni između zagrada), a rezultirajuće vrijednosti se koriste kao argumenti funkcije. 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 nakon što je interpretator došao do kraja, vraća se undefined. Ako se funkcija vraća kao rezultat povratnog izraza, vrijednost izraza koji slijedi nakon povratnog izraza se vraća ili je nedefinirana ako izraz return nema izraz.

Metoda nije ništa drugo do funkcija koja je pohranjena kao svojstvo objekta. Ako imate funkciju func i objekt obj, tada možete definirati metodu na obj koja se zove method kao što je prikazano ispod:

// Definirajte jednostavan objekt i funkciju var obj = (); function func(a, b) ( return a+b;) // Dodaj metodu objektu obj obj.method = func; // Sada možete pozvati ovu metodu var result = obj.method(4, 5);

Najčešće, kada pozivate metode, koristite operator tačke za pristup svojstvima, ali možete koristiti i obrazac uglastih zagrada za pristup svojstvima. Na primjer, oba sljedeća izraza su izrazi poziva metode:

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

Argumenti i povratna vrijednost poziva metode se obrađuju na potpuno isti način kao i normalni poziv funkcije. Međutim, poziv metode ima jednu važnu razliku: kontekst poziva. Izraz za pristup svojstvu sastoji se od dva dijela: objekta (u ovom slučaju obj) i imena svojstva (metoda). U takvim izrazima poziva metoda, obj postaje kontekst poziva, a tijelo funkcije može referencirati taj objekt koristeći ključnu riječ this. Na primjer:

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

Metode i ključna riječ this su centralne 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 neke operacije nad objektom, a sintaksa poziva metode jasno odražava činjenicu da funkcija radi na objektu.

Imajte na umu: ovo je ključna riječ, a ne varijabla ili ime svojstva. JavaScript sintaksa ne dozvoljava elementu this da se dodijeli vrijednost.

Argumenti i parametri funkcije

U JavaScript-u, definicije funkcija ne specificiraju tipove parametara, a pozivi funkcija ne izvode nikakvu provjeru tipa na proslijeđenim vrijednostima argumenata. Zapravo, JavaScript čak ni ne provjerava broj argumenata prilikom pozivanja funkcija. Pododjeljci u nastavku opisuju što se događa ako 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.

Opcioni argumenti

Kada je broj argumenata u pozivu funkcije manji od broja deklariranih parametara, argumenti koji nedostaju postavljaju se na nedefinirano. Često je zgodno pisati funkcije tako da su neki od argumenata opcioni i da se mogu izostaviti prilikom pozivanja funkcije. U ovom slučaju, poželjno je osigurati mogućnost dodjeljivanja razumno razumnih zadanih vrijednosti parametrima koji se mogu izostaviti. Na primjer:

// Dodajte nabrojiva imena // svojstava objekta obj u niz arr i vratite ga. Ako argument // arr nije proslijeđen, kreirajte i vratite novu funkciju niza getPropertyNames(obj, /* opcionalno */ arr) ( if (arr === nedefinirano) arr = ; // Ako niz nije definiran, kreirajte a new for(var property in obj) arr.push(property) // Ova funkcija se može pozvati sa 1 ili 2 argumenta: var a = getPropertyNames((x:1, y:1)); // Dobivamo svojstva objekta u novom nizu getPropertyNames((z:5),a); // dodaj svojstva novog objekta ovom nizu console.log(a); // ["x", "y", "z"]

Imajte na umu da kada deklarirate funkcije, neobavezni argumenti moraju dovršiti listu argumenata da bi bili izostavljeni. Programer koji će napisati poziv vašoj funkciji neće moći da prosledi drugi argument i istovremeno izostavi prvi: biće primoran da eksplicitno prenese vrednost nedefinisanu u prvom argumentu. Također obratite pažnju na /* opcioni */ komentar u definiciji funkcije, koji naglašava činjenicu da je parametar opcioni.

Liste argumenata promjenljive dužine

Ako broj argumenata u pozivu funkcije premašuje broj imena parametara, funkcija ne može izravno pristupiti neimenovanim vrijednostima. Rješenje ovog problema pruža Argumenti prigovor. Identifikator u tijelu funkcije argumentima odnosi se na objekt Arguments prisutan u pozivu. Objekt Arguments je objekt sličan nizu koji omogućava da se vrijednosti proslijeđene funkciji dohvate njihovim brojevima, a ne njihovim imenima.

Pretpostavimo da je definirana funkcija func koja zahtijeva jedan argument x. Ako ovu funkciju pozovete s dva argumenta, prvi će biti dostupan unutar funkcije po imenu parametra x ili kao argumenti. Drugi argument će biti dostupan samo kao argumenti. Dodatno, kao i pravi nizovi, argumenti imaju svojstvo dužine koje specificira broj elemenata koje sadrži. To jest, u tijelu funkcije koja se zove func sa dva argumenta, arguments.length ima vrijednost 2.

Objekt Arguments može se koristiti u različite svrhe. Sljedeći primjer pokazuje kako ga koristiti za provjeru da li je funkcija pozvana s ispravnim brojem argumenata, nešto što JavaScript neće učiniti za vas:

Funkcija func(x, y, z) ( // Prvo provjerava da li je proslijeđen ispravan broj argumenata if (arguments.length != 3) ( throw new Error("Func pozvan sa " + arguments.length + " argumentima i potrebno 3."); ) // A sada i sam kod funkcije... )

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

Objekt Arguments ilustruje važnu karakteristiku JavaScript funkcija: one se mogu napisati tako da uzimaju bilo koji broj argumenata. Sljedeća funkcija uzima bilo koji broj argumenata i vraća vrijednost najvećeg (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 za(var i = 0; i m) m = argumenti[i]; // Vratite najveću vrijednost koja se vraća m ) var najveći = maxBroj(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 termin je nastao pojavom programskog jezika C.

Imajte na umu da se promjenljivim funkcijama ne smije dozvoliti pozivanje s praznom listom argumenata. Savršeno je logično koristiti objekt arguments kada pišete funkciju koja očekuje fiksni broj potrebnih imenovanih argumenata, nakon čega slijedi proizvoljan broj neobaveznih neimenovanih argumenata.

Ne zaboravite da argumenti zapravo nisu niz - to je Arguments objekat. Svaki objekat Arguments ima numerisane elemente niza i svojstvo dužine, ali tehnički nije niz. Bolje je o njemu razmišljati kao o objektu koji ima neka numerirana svojstva.

Pored elemenata niza, objekt Arguments definira svojstva pozvani I pozivalac. Pokušaj promjene vrijednosti ovih svojstava u strogom načinu rada ECMAScript 5 garantovano će izazvati TypeError izuzetak. Međutim, u opuštenom načinu rada, standard ECMAScript navodi da se svojstvo pozivatelja odnosi na funkciju koja se trenutno izvršava. Svojstvo pozivaoca 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 steku poziva, a svojstvo pozivatelja je posebno korisno za rekurzivno pozivanje neimenovanih funkcija:

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

Svojstva i metode funkcije

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

svojstvo dužine

U tijelu funkcije, svojstvo arguments.length specificira broj argumenata proslijeđenih funkciji. Međutim, svojstvo dužine same funkcije ima drugačije značenje. Ovo svojstvo samo za čitanje vraća broj argumenata koje funkcija očekuje da primi – broj deklariranih parametara.

Sljedeći isječak definira funkciju zvanu check() koja prima niz argumenata od druge funkcije. On uspoređuje svojstvo arguments.length (broj stvarno proslijeđenih argumenata) sa svojstvom arguments.callee.length (broj očekivanih argumenata) kako bi utvrdio da li je funkciji proslijeđeno onoliko argumenata koliko očekuje. Ako se vrijednosti ne poklapaju, izbacuje se izuzetak. Nakon funkcije check() slijedi test funkcija, func(), koja pokazuje kako se koristi funkcija check():

// Ova funkcija koristi arguments.callee, tako da // neće raditi u strogom modu function check(args) ( var current = args.length; // Stvarni broj argumenata var očekivan = args.callee.length; // Očekivani broj argumenti if (stvarno !== očekivano) // Ako se ne poklapaju, izbacuje se izuzetak throw new Error("očekivano: " + očekivano + "; primljeno " + stvarno ) funkcija func(x, y, z); ) ( // Provjerite broj očekivanih i stvarno proslijeđenih argumenata check(arguments); // 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, novokreirani objekt nasljeđuje svojstva tog prototipa objekta.

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

call() i apply() metode

Metode call() i apply() omogućavaju vam da pozovete funkciju indirektno, kao da je to metoda na nekom drugom objektu. Prvi argument i call() i apply() metoda je objekt na kojem se poziva funkcija; ovaj argument specificira 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.apply(obj);

Bilo koji način pozivanja je ekvivalentan sljedećem isječku (pod pretpostavkom da obj nema svojstvo pod imenom m):

Obj.m = funkcija; // Privremeno napravi func metodom obj obj.m(); // Pozovite ga bez argumenata. deleteobj.m; // Ukloni privremeni metod.

U strogom režimu ECMAScript 5, prvi argument metoda call() i apply() postaje vrijednost ovog, čak i ako je jednostavna vrijednost, null ili nedefinirana. U ECMAScript 3 i u lax modu, vrijednosti null i undefined 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đuje se pozvanoj funkciji. Metoda apply() se ponaša kao call() metoda, osim što se argumenti funkciji prosljeđuju kao niz. Ako je funkcija sposobna obraditi proizvoljan broj argumenata, metoda apply() može se koristiti za pozivanje takve funkcije u kontekstu niza proizvoljne dužine.

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

// Ispod su dvije funkcije koje prikazuju svojstva i // vrijednosti svojstava proizvoljnog objekta. Metoda // prikazi se prosljeđuju 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, dokument, obj); // Radi ispravno print2(console.log, console, obj); print1(document.write, obj); // Doći će do izuzetka nezakonitog pozivanja jer print1(console.log, obj); // nemoguće je pozvati ove metode bez kontekstnog objekta

bind() metoda

Metoda bind() se prvi put pojavila u ECMAScript-u 5, ali je lako oponašati u ECMAScript-u 3. Kao što joj ime govori, glavna svrha metode bind() je da veže funkciju za objekt. Ako pozovete func-ov bind() metod i proslijedite mu obj objekt, vratit će novu funkciju. Pozivanje nove funkcije (kao obične funkcije) pozvaće originalnu funkciju func kao metodu na obj. Svi argumenti proslijeđeni novoj funkciji bit će proslijeđeni originalnoj funkciji. Na primjer:

// Funkcija koju želite da povežete funkcija func(y) (vratite this.x + y; ) var obj = (x:1); // Objekt za vezanje za var g = func.bind(obj); // Pozivanje g(x) će pozvati obj.func(x)

Ovaj tip povezivanja je lako implementirati u ECMAScript 3, kao što je prikazano u nastavku:

// Vraća funkciju koja poziva func kao metodu objekta obj // i prosljeđuje joj sve svoje argumente function bind(func, obj) ( if (func.bind) return func.bind(obj); // Koristi metodu bind if dostupno else return function() ( // U suprotnom se veže kao što je prikazano ispod return func.apply(obj, arguments); )

Metoda bind() u ECMAScript-u 5 radi više od samo vezanja funkcije za objekt. Također izvodi djelomično prevođenje: osim vrijednosti this, svi argumenti proslijeđeni metodi bind() nakon prvog argumenta bit će vezani. Djelomična primjena je uobičajena tehnika u funkcionalnom programiranju i ponekad se naziva currying.

Članak 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 operatora povrata.

Šta je funkcija?

Funkcija je nešto set uputstava, kojem možete dati ime, a zatim oslovljavajte ga ovim imenom s bilo kojeg mjesta u programu.

Klasičan primjer korištenja funkcije. Web stranica sadrži JavaScript kod, neki fragment u kojem se ponavlja nekoliko puta. Da biste to izbjegli možete formatirajte ovaj fragment kao funkciju, A onda ga nazovi na pravim mjestima u kodu po imenu ove funkcije. Pozivanje ove funkcijeće značiti izvršenje instrukcija, koji se nalazi u njemu.

Kako organizirati izvršavanje nekog zadatka u JavaScriptu koristeći funkcije? Da biste to učinili obično radite ovo:

  • razbiti zadatak na njegove sastavne dijelove (podzadatke);
  • podzadaci su formalizirani kroz funkcije;
  • razviti glavni kod koristeći pozive kreiranim funkcijama.

Kao rezultat, takav program postaje više strukturiran. Lakše je napraviti razne promjene i dodati nove funkcije.

Deklarisanje i pozivanje funkcije

Operacije sa funkcijom u JavaScript-u mogu se podijeliti u 2 koraka:

  • najava (kreacija) funkcije.
  • poziv (izvršenje) ovu funkciju.

Deklaracija funkcije. Kreiranje funkcije u JavaScript-u počinje pisanjem ključne riječi function , nakon čega slijedi naziv funkcije, nakon čega slijedi x u zagradi ako je potrebno. parametri su navedeni, nakon čega slijede upute koje su zatvorene u vitičaste zagrade.

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

Funkcije ovog tipa u JavaScript-u se pozivaju izjava deklaracije funkcije. Osim ovog tipa, JavaScript također razlikuje funkcije izraz definicije funkcije i izraz funkcije strelice.

Ime funkcije je sastavljeno prema istim pravilima kao i ime varijable. One. može sadržavati slova, brojeve (0-9), znakove "$" i "_". Preporučljivo je koristiti samo slova engleske abecede (a-z, A-Z) kao slova. Ime funkcije, baš kao i ime varijable, ne može početi brojem.

Funkcija može imati onoliko parametara koliko želite ili uopće ne imati. Zagrade su uključene u svakom slučaju. Ako postoji nekoliko parametara, onda ih je potrebno odvojiti zarezom. Parametrima funkcije pristupa se po njihovom imenu.

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

Poziv funkcije. Deklarisana funkcija sama neće biti izvršena. Da biste ga pokrenuli, mora se pozvati. Funkcija se poziva navođenjem njenog imena i dvije zagrade. Argumenti su navedeni unutar zagrada ako je potrebno.

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

Je li funkcija objekt u JavaScriptu?

Funkcije u JavaScript-u su objekti. U JavaScript-u je sve objekt osim šest primitivnih tipova podataka. A ako je funkcija objekt, onda se referenca na nju može pohraniti u varijablu.

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

Nakon ovoga, možete pozvati funkciju na sljedeći način:

Referenca();

Parametri i argumenti funkcije

Argumenti funkcije- to su vrijednosti koje se prosljeđuju funkciji u fazi njenog poziva. Argumenti se odvajaju jedan od drugog pomoću zareza.

// pozivamo funkciju sayWelcome prenoseći joj dva argumenta sayWelcome("Ivan", "Ivanov"); // drugi poziv sayWelcome funkcije sa dva argumenta sayWelcome("Petr", "Petrov");

Parametri funkcije je jedan od načina u JavaScriptu na koji možete pristupiti argumentima unutar funkcije. Parametri funkcije u fazi njene deklaracije su opisani u zagradama.

Drugim riječima parametri funkcije- to su lokalne varijable koje se kreiraju automatski u fazi pokretanja funkcije. Parametri primaju kao vrijednosti odgovarajuće argumente proslijeđene funkciji tokom njenog poziva. Možete pristupiti parametrima samo unutar ove funkcije, oni ne postoje.

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

U JavaScriptu, prilikom pozivanja funkcije broj argumenata ne mora odgovarati broju parametara. Parametri koji nisu bili postavljeni na vrijednost kada su pozvani bit će jednaki nedefiniranom.

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

// poziva funkciju sayWelcome i prosljeđuje joj jedan argument sayWelcome("Peter"); // Welcome, undefined Peter // poziva funkciju sayWelcome bez prosljeđivanja argumenata sayWelcome(); // Dobrodošli, undefined undefined

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

// deklaracija funkcije funkcija outputParam(param1, param2, param3) ( console.log(param1 + "; " + param2 + "; " + param3); ) // poziva funkciju outputParam prenoseći joj drugačiji broj parametara outputParam( "Kiša" "Snijeg", "Magla"); // Rain; Snijeg; Param izlaza magle(17); // 17; nedefinisano; undefined outputParam(24,33); // 24; 33; undefined outputParam(); // undefined; nedefinisano; nedefinisano

Drugi način pristupa argumentima 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 - će vam omogućiti da dobijete prvi argument, argumenti - drugi argument, itd.

// deklaracija funkcije sum funkcija sum(num1, num2) ( /* num1 ili argumenti – dobiti vrijednost argumenta 1 broj2 ili argumenti – dobiti vrijednost argumenta 2 */ var sum1 = num1 + num2, sum2 = argumenti + argumenti; return "Zbroj, dobijen 1. metodom je jednak " + sum1 + "; zbroj dobijen 2. metodom je " + sum2 ) /* ispisuje rezultat funkcije sume u konzolu 7 - prvi argument (it može se pristupiti preko imena num1 ili pomoću argumenata) 4 - drugi argument (može mu se pristupiti preko imena num2 ili pomoću argumenata) */ console.log(sum(7,4));

Glavna razlika između ovih metoda je u tome što vam prva od njih omogućava pristup samo onim argumentima koji su dobili imena u fazi deklaracije funkcije. Druga metoda vam omogućava da dobijete vrijednost bilo kojeg argumenta, čak i ako nema ime (po serijskom broju). Ova karakteristika JavaScript jezika omogućava vam da kreirate univerzalne, fleksibilne funkcije.

Osim primanja argumenata, objekt arguments vam također omogućava da znate njihov broj. Ovo se radi pomoću svojstva dužine.

Prođite kroz argumente, proslijeđen funkciji, možete, na primjer, koristiti for petlju ili for...of .

// deklaracija funkcije sum funkcija sum() ( var i = 0; console.log("Izlaz svih argumenata koristeći for petlju"); 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 prikazuje na konzoli sve argumente koji su joj proslijeđeni i njihov broj:

// funkcija deklaracije funkcije myFunction () ( var i; console.log("Broj proslijeđenih parametara = " + arguments.length); // prođimo kroz 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 vrši dodavanje svih argumenata koji su joj proslijeđeni (njihov broj je unaprijed nepoznat):

// deklaracija funkcije var myCalc = function() ( // prođimo kroz sve parametre koristeći for petlju var i, sum = 0; for (i = 0; i lt; arguments.length; i++) ( sum += argumenti [i] ) // vraćanje sume kao rezultat return sume ) // poziv funkcije (izlaz u konzolu) console.log(myCalc(4, 20, 17, -6));

Kao rezultat, koristeći objekt arguments, možete implementirati sljedeće u tijelo funkcije:

  • provjera broja proslijeđenih argumenata;
  • obrada bilo kojeg broja parametara.

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

Default Settings

Od ECMAScript 2015 (6) parametar funkcije možete postaviti vrijednost koju će imati po defaultu.

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

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

Prije ECMAScript 2015, mogli ste postaviti parametar na njegovu zadanu vrijednost, na primjer, ovako:

Funkcija setBGColor(color) ( boja = boja !== undefined ? boja: "#009688"; // postavlja boju na zadanu vrijednost "#009688" document.body.style.backgroundColor = boja; )

Preostali parametri

Ako joj prilikom pozivanja prosledite više argumenata nego što ima parametara, onda preostale možete dobiti pomoću tzv. preostali parametri (patametri odmora). Ova funkcija se pojavila u jeziku od ECMAScript 2015.

// ...nums - preostali parametri, kojima se u ovom slučaju može pristupiti po imenu nums function doMath(mathAction, ...nums) ( var rezultat = 0; nums.forEach(function(value) (switch ( mathAction) ( slučaj "suma": 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("sum", 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)

povratna izjava

Naredba return ima za cilj da vrati vrijednost ili rezultat evaluacije izraza trenutne funkcije. Vrijednost ili izraz mora biti odvojen od povrata razmakom. Osim toga, naredba return zaustavlja izvršavanje funkcije, tj. sve instrukcije koje slijede neće biti izvršene.

Funkcija u JavaScriptu uvijek vraća rezultat, bez obzira da li se koristi 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"); // ispisuje vrijednost varijable na konzoli console.log(person); //Instrukcija koja će na konzolu izvesti rezultat funkcije sayWelcome console.log(sayWelcome("Petr","Petrov")); // Instrukcija koja će na konzolu izvesti rezultat funkcije sayWelcome console.log(sayWelcome("Sidorov")); JavaScript - Funkcija s provjerom parametara

Funkcija u JavaScript-u uvijek vraća rezultat kao rezultat svog izvršenja, čak i ako nije eksplicitno definirana pomoću naredbe return. Ovaj rezultat je nedefinisan.

// 1. funkcija koja ne vraća nikakvu rezultatsku funkciju sayWelcome (userFirstName, userLastName) ( console.log("Welcome, " + userLastName + " " + userFirstName); ) // hajde da pokušamo dobiti rezultat iz funkcije koja radi ne vraća ništa console .log(sayWelcome("Ivan", "Ivanov")); // 2. funkcija koja sadrži izraz return bez funkcije vrijednosti sayDay (dan) ( dan = "Danas," + dan; return; //ova instrukcija neće biti izvršena jer dolazi nakon povratne izjave console.log(day) ) // pokušajmo dobiti rezultat iz funkcije koja sadrži izraz return bez vrijednosti console.log(sayDay("21. februar 2016")); JavaScript - Dobijte vrijednost iz funkcije koja ništa ne vraća

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

Preopterećenje funkcije u JavaScript-u

Preopterećenje funkcija u programiranju je mogućnost deklariranja nekoliko funkcija s istim imenima u istom opsegu. Takve se funkcije razlikuju jedna od druge po vrsti i broju argumenata. Svaka funkcija ima svoju logiku programa. Preopterećenje funkcije se koristi tako da se slične radnje mogu izvesti pomoću jednog imena funkcije.

Jezik JavaScript ne podržava preopterećenje funkcija na isti način kao što je implementiran, na primjer, u jezicima sličnim C. One. U JavaScriptu ne možete kreirati više funkcija sa istim imenima koje su u istom opsegu.

Slična funkcionalnost se može implementirati u JavaScript koristeći sljedeće korake:

  • Da biste provjerili da li je argument proslijeđen ili ne, koristite uvjet koji provjerava njegovu vrijednost za undefined.
  • Da biste provjerili broj argumenata proslijeđenih funkciji, koristite svojstvo dužine argumenata objekta.
  • Da biste saznali tip proslijeđene vrijednosti argumenta, koristite operatore typeof ili instanceof.
  • Za rad s promjenjivim brojem argumenata, koristite objekt arguments.
  • Počevši od ECMAScript6, možete odrediti 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,elements) ( //ako parametar elemenata nije specificiran prilikom pozivanja if (elements=== undefined) ( //tada postavite njegovu vrijednost na "div " elements = "div "; ) //dobijemo sve elemente elemente = $(elements); //iterirajmo sve elemente i postavimo ih na specificiranu boju pozadine elements.each(function())( $(this).css(" background-color",bgColor) ; )); ) /*Pozovite setBgColor funkciju, specificirajući jedan parametar. Jer 2 parametar nije naveden, onda će ova funkcija promijeniti boju pozadine svih div elemenata.*/ setBgColor("green"); /*Pozovite setBgColor funkciju, specificirajući 2 parametra. Jer 2 je naveden parametar, onda će ova funkcija promijeniti boju pozadine samo elemenata gumba.*/ setBgColor("#ff0000","button");

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

//deklaracija funkcije koja mijenja boju pozadine elemenata //parametar elemenata ima vrijednost "div" prema zadanoj funkciji setBgColor(bgColor,elements = "div") ( //dobijemo sve elemente elemente = $(elements); //iteriraj sve elemente i postavi ih na specificiranu boju pozadine elements.each(function())( $(this).css("background-color",bgColor); ) ) //pozovi funkciju setBgColor, specificirajući jedan parametar setBgColor("green"); //pozovite funkciju setBgColor, specificirajuć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 funkcije countCal(sex, height) ( // parametri: spol (spol) i visina (visina) var rezultat; if ((sex === 0) || (sex === "muškarac") ) ( rezultat = (visina - 100) * 20; ) else if ((spol === 1) || (spol === "žena")) ( rezultat = (visina - 105) * 19; ) if (rezultat ) ( // argumenti - nivo aktivnosti if (argumenti) ( rezultat *= argumenti; ) console.log("Količina kcal za normalan život: " + rezultat); ) else ( console.log("Nevažeći parametri"); ) ) / * poziva funkciju i prosljeđuje joj 2 argumenta (1 - "man", može se pristupiti korištenjem imena sex i argumenata; 2 - vrijednost 185, može se pristupiti korištenjem imena sex i argumenata) */ countCal ("muškarac", 185); /* poziva funkciju i prosljeđuje joj 3 parametra, iako su samo 2 prisutna u opisu funkcije (u ovom slučaju vrijednost 3. parametra možete dobiti samo kao argumente) */ countCal(0, 185, 2);

Rekurzija

Rekurzija je poziv samoj sebi unutar tijela neke funkcije.

Funkcija se obično poziva ovisno o tome kako je deklarirana imenom ili promjenljivom koja sadrži referencu na funkciju.

Funkcija fact(n) ( if (n === 1) ( return 1; ) return fact(n-1) * n; ) console.log(fact(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 ovu nekretninu, jer... to je zastarjelo. Osim toga, u strogom načinu rada uopće ne radi.

Šta su ugrađene (standardne) funkcije?

JavaScript ima ogroman skup ugrađenih (standardnih) funkcija. Ove funkcije su već opisane u samom pretraživaču. Gotovo svi su metode jednog ili drugog objekta.

Na primjer, da bi se pozvala ugrađena funkcija (metoda) upozorenje, ne mora se prvo deklarirati. Već je opisano u pretraživaču. Metoda upozorenja se poziva navođenjem imena, zagrada i argumenta unutar njih. Ova metoda je dizajnirana da prikaže poruku na ekranu u obliku dijaloškog okvira. Tekstualna poruka se uzima iz vrijednosti parametra ove funkcije.

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

Funkcije su jedan od osnovnih gradivnih blokova u JavaScript-u. 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. Pročitajte više o objektima i metodama u Rad s objektima.

Funkcije poziva

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

Kvadrat(5);

Prethodni izraz poziva funkciju s argumentom 5. Funkcija izvršava svoje izraze 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)); /* ... */ funkcija square(n) (vrati n * n; )

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

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

Console.log(kvadrat); // kvadrat je podignut sa nedefiniranom početnom vrijednošću. console.log(kvadrat(5)); // TypeError: square nije funkcija var square = function(n) (vraćanje 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:

Funkcija factorial(n) (ako ((n === 0) || (n === 1)) vrati 1; inače vrati (n * factorial(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 = factorial(2); // b dobiva vrijednost 2 c = factorial(3); // c dobiva vrijednost 6 d = factorial(4); // d dobiva vrijednost 24 e = factorial(5); //e dobija vrijednost 120

Postoje i drugi načini za pozivanje funkcija. Često postoje slučajevi u kojima se funkcija treba dinamički pozvati, ili broj argumenata funkcije varira, ili u kojima se kontekst poziva funkcije treba postaviti na određeni objekt određen u vrijeme izvođenja. Ispostavilo se da su funkcije same po sebi objekti, a ti objekti zauzvrat imaju metode (pogledajte objekt Funkcija). Jedna od njih, metoda apply(), 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 su definirane u globalnom opsegu var num1 = 20, num2 = 3, name = "Chamahk"; // Ova funkcija je definirana u funkciji globalnog opsega multiply() (vraćanje num1 * num2; ) multiply(); // Vraća 60 // Funkcija primjer ugniježđene funkcije getScore() ( var num1 = 2, num2 = 3; funkcija add() ( povratno ime + " postignuto " + (num1 + num2); ) return add(); ) getScore (); // Vraća "Chamahk postigao 5"

Opseg i stek funkcija

Rekurzija

Funkcija se može referirati i pozvati 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 = function bar() ( // naredbe idu ovdje);

Unutar tijela funkcije, sljedeće su sve ekvivalentne:

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

Funkcija koja sama sebe poziva naziva se a rekurzivna funkcija. Na neki način, rekurzija je analogna petlji. Oba izvršavaju isti kod više puta, i oba zahtijevaju uvjet (da 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:

Funkcija loop(x) ( if (x >= 10) // "x >= 10" je izlazni uslov (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, dobijanje svih čvorova strukture stabla (npr. DOM) se lakše radi pomoću rekurzije:

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

U poređenju sa 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 upotreba steka. U stvari, sama rekurzija koristi stek: stek funkcija.

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

Funkcija foo(i) (ako je (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 (unutrašnja) funkcija je privatna za svoju (vanjsku) funkciju koja sadrži. Takođe formira a zatvaranje. Zatvaranje je izraz (obično funkcija) koji može imati slobodne varijable zajedno sa okruženjem koje povezuje 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.

  • Unutrašnjoj funkciji se može pristupiti samo iz naredbi u vanjskoj funkciji.
  • Unutrašnja funkcija formira zatvaranje: unutrašnja funkcija može koristiti argumente i varijable vanjske funkcije, dok vanjska funkcija ne može koristiti argumente i varijable unutrašnje funkcije.

Sljedeći primjer prikazuje ugniježđene funkcije:

Funkcija addSquares(a, b) ( funkcija square(x) ( return x * x; ) return square(a) + square(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 formira zatvaranje, možete pozvati vanjsku funkciju i specificirati argumente i za vanjsku i za 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 = outside(3)(5); // vraća 8

Očuvanje varijabli

Obratite pažnju 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 samo kada vraćena unutra nije više dostupna.

Ovo se ne razlikuje od pohranjivanja referenci u druge objekte, ali je često manje očigledno jer se reference ne postavljaju direktno 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, pošto 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" biće objašnjeno kasnije.)

Razmotrite sljedeći primjer:

Funkcija A(x) ( funkcija B(y) ( funkcija C(z) ( console.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 . Ovo se može uraditi jer:

  1. B formira zatvaranje uključujući A, tj. B može pristupiti A-ovim argumentima i varijablama.
  2. C formira 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 A "s argumenti i varijable. Drugim riječima, C lancima opsege B i A tim redoslijedom.

Obrnuto, međutim, nije tačno. 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 unutrašnjih opsega ima prednost, tako da unutrašnji 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 domet. Uzmite u obzir sljedeće:

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

Konflikt imena se događa u naredbi return x i nalazi se između unutar "s parametra x i van "s 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 karakteristika JavaScript-a. JavaScript dozvoljava ugniježđenje funkcija i daje unutrašnjoj funkciji potpuni pristup svim varijablama i funkcijama definiranim unutar vanjske funkcije (i svim drugim varijablama i funkcijama kojima vanjska funkcija ima pristup). Međutim, vanjska funkcija nema pristup varijablama i funkcijama definiranim unutar unutarnje funkcije. Ovo pruža neku vrstu enkapsulacije za varijable unutrašnje funkcije. Također, budući da unutarnja funkcija ima pristup opsegu vanjske funkcije, varijable i funkcije definirane u vanjskoj funkciji živjet će duže od trajanja izvršenja vanjske funkcije, ako unutarnja funkcija uspije preživjeti izvan vijeka trajanja vanjske funkcije. funkcija. Zatvaranje se stvara kada se unutarnja funkcija nekako učini dostupnom bilo kojem opsegu izvan vanjske funkcije.

Var pet = function(name) ( // Vanjska funkcija definira varijablu pod nazivom "name" var getName = function() ( povratno ime; // Unutrašnja funkcija ima pristup varijabli "name" vanjske //funkcije) return getName; // Vraća unutrašnju funkciju, izlažući je na taj način vanjskom opsegu ) myPet = pet("Vivie"); moj kućni ljubimac(); // Vraća "Vivie"

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

Var createPet = function(name) (var sex; return (setName: function(newName) (name = newName; ), getName: function() (povratno ime; ), getSex: function() (povratak sex;), setSex: function(newSex) ( if(typeof newSex === "string" && (newSex.toLowerCase() === "muški" || newSex.toLowerCase() === "ženski")) ( sex = newSex; ) ) ) ) var pet = createPet("Vivie"); pet.getName(); // Vivie pet.setName("Oliver"); pet.setSex("muško"); pet.getSex(); // muški pet.getName(); // Oliver

U kodu iznad, naziv varijabli vanjske funkcije je dostupan unutarnjim funkcijama, i ne postoji drugi način da se pristupi unutrašnjim varijablama osim kroz unutrašnje funkcije. Unutrašnje varijable unutrašnjih funkcija djeluju kao sigurno spremište za vanjske argumente i varijable. Oni drže "trajne" i "inkapsulirane" podatke za unutrašnje funkcije za rad. Funkcije čak ne moraju biti dodijeljene varijabli ili imaju ime.

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

Međutim, postoji niz zamki na koje treba paziti kada koristite zatvarače. Ako zatvorena funkcija definira varijablu s istim imenom kao i ime varijable u vanjskom opsegu, ne postoji način da se ponovo uputi na varijablu u vanjskom opsegu.

Var createPet = function(name) ( // Vanjska funkcija definira varijablu pod nazivom "name". return ( setName: function(name) ( // Priložena funkcija također definira varijablu pod nazivom "name". name = name; // Kako možemo pristupiti "imenu" definiranom vanjskom funkcijom ) ) )

Korištenje objekta argumenata

Argumenti funkcije se održavaju 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 bio arguments. Ukupan broj argumenata je označen argumentima.length.

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 string koji specificira znakove koji razdvajaju stavke za spajanje. Funkcija je definirana na sljedeći način:

Funkcija myConcat(separator) ( var result = ""; // inicijalizacija liste var i; // iteracija 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, narandžasto, plavo, " myConcat(", ", "crveno", "narandžasto", "plavo"); // vraća "elephant; žirafa; lav; gepard; " myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // vraća "žadulja. bosiljak. origano. biber. peršin. " myConcat(". ", "žadulja", "bosiljak", "origano", "biber", "peršun");

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

Na uvođenje funkcija strelica utjecala su dva faktora: kraće funkcije i neobavezivanje ove.

Kraće funkcije

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

Var a = [ "Vodik", "Helijum", "Litijum", "Berilijum" ]; var a2 = a.map(funkcija(e) (vraćanje s.dužine; )); console.log(a2); // zapisi var a3 = a.map(s => s.length); console.log(a3); // logs

Nema ovo odvojeno

Sve do funkcija sa strelicama, 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.). Ovo se pokazalo manje nego idealno sa objektno orijentisanim stilom programiranja.

Funkcija Person() ( // Konstruktor Person() definira `ovo` kao sebe. this.age = 0; setInterval(function growUp() ( // U nestriktnom načinu rada, growUp() funkcija definira `ovo` // kao globalni objekat, koji se razlikuje od `this` // definiranog od strane konstruktora this.age++ ), 1000 ) var p = new Person();

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

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

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

Var add = function(arg1, arg2) (var sum = arg1 + arg2; return sum; ) var result = add(5, 2); //rezultat je sada 7

To jest, funkcija, prvo, nema ime. Drugo, dodeljuje se promenljivoj, ali ne samo da se dodeljuje, već njeno telo ide upravo tamo. Lično, kod mene, koji sam ranije pisao na jezicima kao što su VB, C++, ovakva najava izazvala je zbunjenost i nerazumijevanje kako to funkcionira i zašto je uopće tako pisati.

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

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

I tu dolazimo do karakteristika funkcija u Javascriptu. Radi lakšeg razumijevanja, zamislite da je funkcija u JS-u redovna vrijednost, poput broja ili stringa. 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 zamislite da je funkcija obična vrijednost, iako vrlo složene strukture, onda se prvi način deklaracije više ne čini nevjerovatnim.

Sljedeća zanimljivost je logičan nastavak prve. Nakon što stavimo podatke u varijablu, možemo koristiti ime te varijable da prenesemo podatke u drugu varijablu:

Var a = 5; var b = a; upozorenje(b); // će izbaciti 5

Uobičajena stvar. Sada pogledajte ovaj kod:

Var add = funkcija(arg1, arg2) (var suma = arg1 + arg2; povratna suma; ) var calcSum = add; upozorenje(zbroj izračuna(5, 6)); // će ispisati 11

Počinješ li 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 = add(1, 1); //calcSum je sada jednak 2, ovo nije funkcija, već varijabla sa brojem alert(calcSum(5, 6)); //greška

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

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

Var calcFact = function fact(val) ( if (val == 1) ? val: val * fact(val - 1); //izračunavanje faktorijala korištenjem rekurzije ) alert(calcFact(4)); //ispisat će se 24

Ovdje, kada smo dodijelili funkciju varijabli, nazvali smo je činjenica. Međutim, ovo ime će biti dostupno samo unutar same funkcije i nigdje drugdje. Razlozi za to leže u principu rada tumača i izvan su okvira lekcije.

Možda se pitate: „Hm, zanimljiva prilika, ali koja je prednost ove metode? Neću reći da postoje situacije u kojima je nemoguće bez takvog pristupa, ali mogu navesti primjer gdje se smanjuje količina koda. Recimo da trebate pozdraviti osobu u zavisnosti od doba dana:

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

Kao što vidite, funkcije su izuzetno jednostavne, sa jednom komandom za upozorenje.

Ako bismo odlučili da idemo "klasičnim putem", morali bismo napisati tri odvojene funkcije i zatim ih pozvati u uvjetu provjere vremena:

Funkcija goodMorning() ( alert("Dobro jutro!"); ) funkcija goodAfternoon() ( alert("Dobar dan!"); ) funkcija goodEvning() ( alert("Dobro veče!"); ) var date = new Date (); (datum.getHours()< 12) ? goodMorning() : (date.getHours() < 18) ? goodAfternoon() : goodEvning();

Kod je vizuelno značajno narastao, čak i s obzirom na to da smo koristili kratku formu uslovnog iskaza. Ako pretpostavimo da datoteka sadrži zaista važne funkcije koje obavljaju proračune, onda pretrpavanje liste takvim mini funkcijama koje nemaju važnu logiku, a koje se najvjerovatnije koriste samo jednom, nije dobra ideja. Osim toga, primorani smo svakoj funkciji dati jedinstveno ime i naznačiti ga prilikom pozivanja. Stoga, ako trebate promijeniti ime jednog od njih, morat ćete ga promijeniti na dva mjesta, što povećava vjerovatnoću greške.

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

Funkcija add(a, b) ( return a + b; ) var calcSum = add; calcSum(5, 5);

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

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

I u prvom slučaju biće dovoljno samo napisati hello(); a rezultat će biti isti.

Rekao sam vam o zanimljivoj osobini JS funkcija i dao primjere. Videli ste to načine pozivanja funkcija u Javascript-u nisu ograničeni samo na jednu vrstu. Čak i ako ne možete odmah pronaći upotrebu ovih sposobnosti u svojim projektima, barem ćete znati da takve mogućnosti postoje. A kada se ukaže zaista dobra prilika, možete smanjiti količinu koda i izbjeći nepotrebnu zabunu i greške!

Ovaj članak pokriva karakteristike Javascript jezika: kreiranje, parametre, tehnike, zatvaranja i još mnogo toga.

Kreiranje funkcija

Postoje 3 načina za kreiranje funkcije. Glavna razlika u rezultatu njihovog rada je u tome što je imenovana funkcija vidljiva svuda, a anonimna je vidljiva tek nakon njene deklaracije:

Funkcije - objekti

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

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

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

Na primjer,

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

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

U primjeru je bilo nemoguće napraviti zadatak:

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 jedan), više o tome u nastavku u odjeljku o parametrima.

Obim

Svaka funkcija, ili čak i svako pokretanje funkcije, postavlja svoj individualni opseg.

Varijable se mogu deklarirati bilo gdje. Ključna riječ var specificira varijablu u trenutnom opsegu. Ako je zaboravite, varijabla će završiti u globalnom objektu prozora. Moguća su neočekivana ukrštanja sa drugim varijablama prozora, konflikti i kvarovi.

Za razliku od nekih jezika, blokovi ne definiraju poseban opseg. Nema razlike da li je varijabla definirana unutar ili izvan bloka. Dakle, ova dva isječka su potpuno ekvivalentna:

Varijabla specificirana putem var je vidljiva svuda u opsegu, čak i prije operatora var. Na primjer, napravimo funkciju koja će promijeniti varijablu, var za koju je ispod.

Na primjer:

Funkcija a() ( z = 5 // će promijeniti z lokalno.. // .. budući da je z deklariran preko var var z ) // testirati brisanje z // obrisati globalno z a() alert(window.z) upravo u case // => nedefinirano, jer je z promijenjen lokalno

Parametri funkcije

Funkcije se mogu izvoditi s bilo kojim brojem parametara.

Ako je funkciji proslijeđeno manje parametara nego što je u definiciji, onda se oni koji nedostaju smatraju nedefiniranima.

Sljedeća funkcija vraća vrijeme potrebno za prelazak udaljenosti pri jednakoj brzini.

Kada se pokrene prvi put, funkcija radi sa argumentima distance=10, speed=undefined. 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 JavaScript-u ne vraća true/false, već samu vrijednost (prvu koja se konvertuje u true).

Stoga se koristi za postavljanje zadanih vrijednosti. U našem pozivu brzina će biti izračunata kao nedefinisano || 10 = 10.

Stoga će rezultat biti 10/10 = 1.

Drugo lansiranje je standardno.

Treće pokretanje specificira nekoliko dodatnih argumenata. Funkcija ne predviđa rad s dodatnim argumentima, pa se oni jednostavno zanemaruju.

Pa, u posljednjem slučaju uopće nema argumenata, tako da distance = undefined , i imamo rezultat dijeljenja undefined/10 = NaN (Nije-A-Broj, došlo je do greške).

Rad sa neodređenim brojem parametara

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

  1. Pozovite argumente, počevši od nule
  2. Dužina u svojstvu dužine
  3. Veza do same funkcije u svojstvu pozvanog

Na primjer,

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

Svojstvo arguments slično je nizu po tome što ima dužinu i numeričke indekse. U stvari, argumenti ne pripadaju klasi Array i ne sadrže njene 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 pored prve, možete kreirati 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 = function(a,b) (alert(a+b)) var arr = func.apply(null, arr) // => alert(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 niza arr i vraća rezultirajući niz:

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

Primjer upotrebe:

Map(run, ) // =

Ili možete kreirati anonimnu funkciju direktno u pozivu mape:

// anonimna funkcija utrostručuje brojeve map(funkcija (a) ( return a*3 ) , ) // =

Sažimanje parametara u objekt

Postoje funkcije čiji se argumenti jako razlikuju.

Na primjer:

// možete navesti samo dio argumenata // oni koji nisu navedeni se izračunavaju ili uzimaju zadanom funkcijom resize(toWidth, toHeight, saveProportions, animate) ( // zadane vrijednosti saveProportions = saveProportions || true animate = animate || true toHeight = toHeight |.)

Poziv sa opcionim parametrima se mora obaviti ovako:

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

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

Funkcija resize(setup) ( // zadane vrijednosti var saveProportions = setup.saveProportions || true var animate = setup.animate || true var toHeight = setup.toHeight || ... )

Poziv je sada mnogo jednostavniji:

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

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

Osim toga, praktičnije je napraviti nizove poziva s objektom kao što je:

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

Najbolji članci na ovu temu