JavaScript funkcijas. Izteiksmīgs JavaScript: Funkcijas Funkcijas kā vērtības

Cilvēki domā, ka datorzinātnes ir ģēniju māksla. Reāli ir otrādi – vienkārši daudzi cilvēki dara lietas, kas stāv viena otrai virsū, it kā veidotu sienu no maziem oļiem.

Donalds Knuts

Jūs jau esat redzējis funkciju izsaukumus, piemēram, brīdinājumu . Funkcijas ir JavaScript programmēšanas maize un sviests. Ļoti populāra ir ideja ietīt programmas daļu un nosaukt to par mainīgo. Tas ir rīks lielu programmu strukturēšanai, atkārtojumu samazināšanai, nosaukumu piešķiršanai apakšprogrammām un apakšprogrammu izolēšanai vienu no otras.

Acīmredzamākais funkciju lietojums ir jaunas vārdnīcas izveide. Piedāvāt vārdus parastai cilvēku prozai ir slikta forma. Programmēšanas valodā tas ir nepieciešams.

Vidējais pieaugušais krievvalodīgais zina apmēram 10 000 vārdu. Retā programmēšanas valoda satur 10 000 iebūvētu komandu. Un programmēšanas valodas vārdu krājums ir skaidrāk definēts, tāpēc tas ir mazāk elastīgs nekā cilvēka. Tāpēc mums parasti ir jāpievieno savi vārdi, lai izvairītos no nevajadzīgas atkārtošanās.

Funkcijas definīcija

Funkcijas definīcija ir parasta mainīgā definīcija, kur vērtība, ko mainīgais saņem, ir funkcija. Piemēram, šāds kods definē mainīgo kvadrātu, kas attiecas uz funkciju, kas aprēķina noteikta skaitļa kvadrātu:

var kvadrāts = funkcija(x) (atgriešanās x * x; ); konsole.log(kvadrāts(12)); // → 144

Funkciju izveido izteiksme, kas sākas ar funkcijas atslēgvārdu. Funkcijām ir parametru kopa (šajā gadījumā tikai x) un pamatteksts, kas satur instrukcijas, kas jāizpilda, kad funkcija tiek izsaukta. Funkcijas pamatteksts vienmēr ir ietverts cirtainos iekavās, pat ja tas sastāv no viena priekšraksta.

Funkcijai var būt vairāki parametri vai vispār nav neviena. Nākamajā piemērā parametram makeNoise nav parametru saraksta, savukārt jaudai ir divi:

Var makeNoise = function() ( console.log("Fuck!"); ); trokšņot(); // → Muļķības! var jauda = funkcija(bāze, eksponents) ( vari rezultāts = 1; for (var skaits = 0; skaits< exponent; count++) result *= base; return result; }; console.log(power(2, 10)); // → 1024

Dažas funkcijas atgriež vērtību, piemēram, jauda un kvadrāts, citas ne, piemēram, makeNoise, kam ir tikai blakusefekts. Atgriešanas priekšraksts definē funkcijas atgriezto vērtību. Kad programmas apstrāde sasniedz šo instrukciju, tā nekavējoties iziet no funkcijas un atgriež šo vērtību koda vietā, no kuras funkcija tika izsaukta. return bez izteiksmes atgriež undefined .

Parametri un darbības joma

Funkciju parametri ir tāpat kā mainīgie, taču to sākotnējās vērtības tiek iestatītas, kad funkcija tiek izsaukta, nevis tās kodā.

Svarīga funkciju īpašība ir tāda, ka funkcijā izveidotie mainīgie (ieskaitot parametrus) ir lokāli šajā funkcijā. Tas nozīmē, ka jaudas piemērā rezultāta mainīgais tiks izveidots ikreiz, kad funkcija tiks izsaukta, un šie atsevišķie tā iemiesojumi nekādā veidā nav saistīti viens ar otru.

Šī mainīgo atrašanās vieta attiecas tikai uz parametriem un mainīgajiem, kas izveidoti funkcijās. Mainīgos, kas iestatīti ārpus jebkuras funkcijas, sauc par globālajiem mainīgajiem, jo ​​tie ir redzami visā programmā. Šādiem mainīgajiem var piekļūt arī funkcijā, ja vien neesat deklarējis lokālu mainīgo ar tādu pašu nosaukumu.

Sekojošais kods to ilustrē. Tas definē un izsauc divas funkcijas, kas piešķir vērtību x. Pirmais to deklarē kā lokālu, tādējādi mainot tikai vietējo mainīgo. Otrais nedeklarē, tāpēc darbs ar x funkcijas iekšpusē attiecas uz globālo mainīgo x, kas tika iestatīts piemēra sākumā.

var x = "ārpus"; var f1 = funkcija() ( var x = "f1 iekšpusē"; ); f1(); konsoles žurnāls(x); // → ārpus var f2 = function() ( x = "f2 iekšpusē"; ); f2(); konsoles žurnāls(x); // → f2 iekšpusē

Šāda rīcība palīdz novērst nejaušu funkciju mijiedarbību. Ja visi mainīgie tiktu izmantoti jebkur programmā, būtu ļoti grūti pārliecināties, ka viens mainīgais netiek izmantots dažādiem mērķiem. Un, ja jūs atkārtoti izmantotu mainīgo, jūs saskartos ar dīvainiem efektiem, kad trešās puses kods sajaucas ar jūsu mainīgā vērtībām. Apstrādājot funkciju lokālos mainīgos tā, lai tie pastāvētu tikai funkcijā, valoda ļauj strādāt ar funkcijām tā, it kā tās būtu atsevišķi mazi visumi, kas ļauj neuztraukties par visu kodu kopumā.

Ligzdotie tvērumi

JavaScript atšķir ne tikai globālos un lokālos mainīgos. Funkcijas var definēt funkcijās, kā rezultātā rodas vairāki lokalizācijas līmeņi.

Piemēram, šajā diezgan bezjēdzīgajā funkcijā ir iekļautas vēl divas funkcijas:

var ainava = funkcija() ( var rezultāts = ""; var flat = funkcija(izmērs) ( for (var count = 0; count< size; count++) result += "_"; }; var mountain = function(size) { result += "/"; for (var count = 0; count < size; count++) result += """; result += "\\"; }; flat(3); mountain(4); flat(6); mountain(1); flat(1); return result; }; console.log(landscape()); // → ___/""""\______/"\_

Plakanās un kalnu funkcijas redz rezultāta mainīgo, jo tās atrodas funkcijā, kurā tas ir definēts. Bet viņi nevar redzēt viens otra skaita mainīgos, jo vienas funkcijas mainīgie ir ārpus otras funkcijas. Un vide ārpus ainavas funkcijas neredz nevienu no šajā funkcijā definētajiem mainīgajiem.

Īsāk sakot, katrā lokālajā tvērumā varat redzēt visus tvērumus, kas to satur. Funkcijā pieejamo mainīgo lielumu kopu nosaka vieta, kur šī funkcija ir deklarēta programmā. Ir redzami visi mainīgie no blokiem, kas apņem funkcijas definīciju, ieskaitot tos, kas definēti augstākais līmenis galvenajā programmā. Šo pieeju tvērumiem sauc par leksisko.

Cilvēki, kuri ir mācījušies citas programmēšanas valodas, varētu domāt, ka jebkurš bloks, kas ievietots cirtainos iekavās, rada savu lokālo vidi. Bet JavaScript tvērumu veido tikai funkcijas. Varat izmantot atsevišķus blokus:

var kaut kas = 1; ( var kaut ko = 2; // Dariet kaut ko ar mainīgo kaut ko... ) // Iziet no bloka...

Bet kaut kas bloka iekšpusē ir tāds pats mainīgais kā ārpusē. Lai gan šādi bloki ir atļauti, ir jēga tos izmantot tikai priekšrakstiem un cilpām.

Ja tas jums šķiet dīvaini, tas tā šķiet ne tikai jums. JavaScript 1.7 ieviesa atslēgvārdu let, kas darbojas kā var, bet rada mainīgos, kas ir lokāli jebkuram blokam, ne tikai funkcijai.

Funkcionē kā vērtības

Funkciju nosaukumus parasti izmanto kā programmas daļas nosaukumu. Šāds mainīgais ir vienreiz iestatīts un nemainās. Tāpēc ir viegli sajaukt funkciju ar tās nosaukumu.

Bet tās ir divas dažādas lietas. Funkcijas izsaukumu var izmantot kā vienkāršu mainīgo - piemēram, tos var izmantot jebkurā izteiksmē. Ir iespējams saglabāt funkcijas izsaukumu jaunā mainīgajā, nodot to kā parametru citai funkcijai utt. Arī mainīgais, kas saglabā funkcijas izsaukumu, paliek parasts mainīgais, un tā vērtību var mainīt:

Var launchMissiles = funkcija(vērtība) ( raķešu sistēma. launch("lūdzu!"); ); if (safeMode) launchRaķetes = funkcija(vērtība) (/* izlaidums */);

5. nodaļā mēs apspriedīsim brīnišķīgās lietas, ko var paveikt, nododot funkciju izsaukumus citām funkcijām.

Funkciju deklarācija

Izteicienam “var kvadrāts = funkcija…” ir arī īsāka versija. Funkcijas atslēgvārdu var izmantot priekšraksta sākumā:

funkcija kvadrāts(x) (atgriež x * x; )

Šī ir funkciju deklarācija. Paziņojums definē mainīgo kvadrātu un piešķir tam doto funkciju. Pagaidām viss ir ok. Šādā definīcijā ir tikai viena kļūme.

Console.log("Nākotne saka:", nākotne()); funkcija future() ( atgriezties "Mums JOPROJĀM nav lidojošu automašīnu."; )

Šis kods darbojas, pat ja funkcija ir deklarēta zem koda, kas to izmanto. Tas ir tāpēc, ka funkciju deklarācijas nav daļa no parastās programmu izpildes no augšas uz leju. Tie "pārvietojas" uz savas darbības jomas augšdaļu, un tos var izsaukt ar jebkuru kodu šajā jomā. Dažreiz tas ir ērti, jo varat rakstīt kodu vissaprātīgākajā secībā, neuztraucoties par to, ka visas iepriekš minētās funkcijas ir jādefinē, kur tās tiek izmantotas.

Bet kas notiek, ja funkcijas deklarāciju ievietojam nosacījuma blokā vai cilpā? Jums tas nav jādara. Vēsturiski dažādas JavaScript palaišanas platformas šādus gadījumus apstrādāja atšķirīgi, un pašreizējais valodas standarts to aizliedz. Ja vēlaties, lai jūsu programmas darbotos konsekventi, izmantojiet funkciju deklarācijas tikai citās funkcijās vai galvenajā programmā.

Funkcijas piemērs() ( funkcija a() () // Normule if (kaut kas) ( funkcija b() () // Ay-yy-yy! ) )

zvanu kaudze
Ir noderīgi sīkāk izpētīt, kā izpildes rīkojums darbojas ar funkcijām. Šeit vienkārša programma ar vairāku funkciju izsaukumiem:

Funkcija greet(who) ( console.log("Sveiks, " + who); ) greet("Semjons"); console.log ("Pokeda");

Tas tiek apstrādāts apmēram šādi: sveiciena izsaukšana izraisa pāreju uz funkcijas sākumu. Tas izsauc iebūvēto funkciju console.log, kas pārņem vadību, veic savu darbību un atgriež kontroli. Tad tas sasniedz sveiciena beigas un atgriežas vietā, no kuras tas tika saukts. Nākamā rinda atkal izsauc console.log.

Shematiski to var parādīt šādi:

Top greet console.log sveiciens top console.log top

Tā kā funkcijai ir jāatgriežas tur, no kurienes tā tika izsaukta, datoram jāatceras konteksts, no kura funkcija tika izsaukta. Vienā gadījumā console.log ir jāmaina atpakaļ uz sveicienu. Citā tas atgriežas programmas beigās.

Vietu, kur dators atceras kontekstu, sauc par steku. Katru reizi, kad funkcija tiek izsaukta, pašreizējais konteksts tiek nospiests steka augšpusē. Kad funkcija atgriežas, tā paceļ augšējo kontekstu no steka un izmanto to, lai turpinātu darbu.

Stack glabāšanai nepieciešama vieta atmiņā. Kad steks kļūst pārāk liels, dators pārtrauc izpildi un izdod tādus ziņojumus kā “steka pārpilde” vai “pārāk liela rekursija”. Sekojošais kods to parāda – tas uzdod datoram ļoti sarežģītu jautājumu, kas noved pie nebeidzamiem lēcieniem starp divām funkcijām. Precīzāk, tie būtu bezgalīgi lēcieni, ja datoram būtu bezgalīgs steks. Patiesībā kaudze pārpilda.

Funkcija cālis() ( return egg(); ) function egg() ( return cālis(); ) konsole. log(chicken() + " atnāca pirmais."); // → ??

Izvēles argumenti
Šis kods ir pilnīgi likumīgs un darbojas bez problēmām:

Alert("Sveiks", "Labvakar", "Sveiki visiem!");

Oficiāli funkcijai ir viens arguments. Taču, šādi izaicinot, viņa nesūdzas. Tas ignorē pārējos argumentus un parāda "Sveiki".

JavaScript ir ļoti saudzīgs attiecībā uz funkcijai nodoto argumentu skaitu. Ja nolaidīsi pārāk daudz, liekie tiks ignorēti. Pārāk maz — trūkstošajiem tiks piešķirta vērtība undefined.

Šīs pieejas trūkums ir tāds, ka funkcijai ir iespējams un pat iespējams nodot nepareizu argumentu skaitu, un neviens jums par to nesūdzēsies.

Pluss ir tas, ka varat izveidot funkcijas, kas izmanto izvēles argumentus. Piemēram, nākamajā jaudas funkcijas versijā to var izsaukt gan ar divi, gan ar vienu argumentu – pēdējā gadījumā eksponents būs vienāds ar divi, un funkcija darbojas kā kvadrāts.

Funkcijas jauda(bāze, eksponents) ( if (eksponents == nedefinēts) eksponents = 2; mainīgais rezultāts = 1; for (var count = 0; count< exponent; count++) result *= base; return result; } console.log(power(4)); // → 16 console.log(power(4, 3)); // → 64

Nākamajā nodaļā mēs redzēsim, kā funkcijas pamatteksts var norādīt precīzu tai nodoto argumentu skaitu. Tas ir noderīgi, jo ļauj izveidot funkciju, kas izmanto neierobežotu skaitu argumentu. Piemēram, console.log izmanto šo rekvizītu un izdrukā visus tam nodotos argumentus:

Console.log("R", 2, "D", 2); // → R 2 D 2

Slēgšanas

Iespēja izmantot funkciju izsaukumus kā mainīgos, kopā ar faktu, ka lokālie mainīgie tiek izveidoti no jauna ikreiz, kad funkcija tiek izsaukta, noved mūs pie interesanta punkta. Kas notiek ar vietējiem mainīgajiem, ja funkcija neizdodas?

Šis piemērs ilustrē šo problēmu. Tā deklarē funkciju wrapValue, kas izveido lokālo mainīgo. Pēc tam tas atgriež funkciju, kas nolasa šo vietējo mainīgo un atgriež tā vērtību.

Funkcija wrapValue(n) ( var localVariable = n; return function() ( return localVariable; ); ) var wrap1 = wrapValue(1); var wrap2 = wrapVērtība(2); konsoles žurnāls(wrap1()); // → 1 konsole.log(wrap2()); // → 2

Tas ir derīgs un darbojas kā nākas - piekļuve mainīgajam saglabājas. Turklāt vienlaikus var pastāvēt vairāki viena un tā paša mainīgā gadījumi, kas vēl vairāk apstiprina faktu, ka vietējie mainīgie tiek atkārtoti izveidoti ar katru funkcijas izsaukumu.

Šo spēju strādāt ar atsauci uz kādu lokālā mainīgā gadījumu sauc par slēgšanu. Funkciju, kas aizver lokālos mainīgos, sauc par aizvēršanas funkciju. Tas ne tikai atbrīvo jūs no raizēm par mainīgu kalpošanas laiku, bet arī ļauj radoši izmantot funkcijas.

Ar nelielām izmaiņām mēs savu piemēru pārvēršam par funkciju, kas reizina skaitļus ar jebkuru doto skaitli.

Funkcijas reizinātājs(faktors) ( atgriešanās funkcija(skaitlis) ( atgriešanās skaitlis * faktors; ); ) var divreiz = reizinātājs(2); konsole.log(divreiz(5)); // → 10

Atsevišķs mainīgais, piemēram, localVariable no wrapValue piemēra, vairs nav vajadzīgs. Tā kā parametrs pats par sevi ir lokāls mainīgais.

Lai sāktu šādi domāt, ir vajadzīga prakse. Laba garīgā modeļa versija ir iedomāties, ka funkcija iesaldē kodu savā ķermenī un iesaiņo to iepakojumā. Kad redzat atgriešanas funkciju (...) (...), domājiet par to kā vadības paneli koda fragmentam, kas ir iesaldēts izmantošanai vēlāk.

Mūsu piemērā reizinātājs atgriež iesaldētu koda daļu, ko mēs saglabājam divreiz mainīgajā. Pēdējā rindā tiek izsaukta mainīgā ietvertā funkcija, kas aktivizē saglabāto kodu (atgriešanas numurs * koeficients;). Tam joprojām ir piekļuve faktora mainīgajam, kas tika definēts, kad tika izsaukts reizinātājs, un tam ir arī piekļuve argumentam, kas tika nodots atsaldēšanas laikā (5) kā skaitliskam parametram.

rekursija

Funkcija var izsaukt sevi, ja tā rūpējas, lai nepārpildītu steku. Šādu funkciju sauc par rekursīvu. Šeit ir alternatīvas eksponēšanas ieviešanas piemērs:

Funkcijas jauda(bāze, eksponents) ( ja (eksponents == 0) atgriež 1; citādi atgriež bāzi * jauda(bāze, eksponents - 1); ) console.log(power(2, 3)); // → 8

Šādi matemātiķi definē eksponenci, un, iespējams, tas šo jēdzienu raksturo elegantāk nekā ciklu. Funkcija sevi izsauc daudzas reizes ar dažādiem argumentiem, lai panāktu vairākkārtēju reizināšanu.

Taču šai realizācijai ir problēma – parastā JavaScript vidē tā ir 10 reizes lēnāka nekā versija ar cilpu. Looping ir lētāks nekā funkcijas izsaukšana.

Ātruma un elegances dilemma ir diezgan interesanta. Pastāv zināma plaisa starp cilvēka ērtībām un mašīnu ērtībām. Jebkuru programmu var paātrināt, padarot to lielāku un sarežģītāku. Programmētājam ir jāatrod pareizais līdzsvars.

Pirmās kāpināšanas gadījumā neelegantā cilpa ir diezgan vienkārša un vienkārša. Nav jēgas to aizstāt ar rekursiju. Tomēr bieži vien programmas strādā ar tik sarežģītiem jēdzieniem, ka vēlas samazināt efektivitāti, palielinot lasāmību.

Pamatnoteikums, kas ir atkārtots daudzas reizes un kuram es pilnībā piekrītu - neuztraucieties par veiktspēju, kamēr neesat pārliecināts, ka programma palēninās. Ja tā, atrodiet detaļas, kas kalpo visilgāk, un tirgojiet tur eleganci, lai nodrošinātu efektivitāti.

Protams, nevajadzētu uzreiz pilnībā ignorēt veiktspēju. Daudzos gadījumos, tāpat kā ar eksponenci, mēs neiegūstam daudz vienkāršības no elegantiem risinājumiem. Dažreiz pieredzējis programmētājs uzreiz redz, ka vienkārša pieeja nekad nebūs pietiekami ātra.

Es to aktualizēju, jo pārāk daudz iesācēju programmētāju pieķeras efektivitātei pat mazās lietās. Rezultāts ir lielāks, sarežģītāks un bieži vien bez kļūdām. Šādu programmu rakstīšana prasa ilgāku laiku, un bieži vien tās nedarbojas daudz ātrāk.

Taču rekursija ne vienmēr ir tikai mazāk efektīva alternatīva cilpām. Dažas problēmas ir vieglāk atrisināt ar rekursiju. Visbiežāk tas ir vairāku koka zaru šķērsošana, no kuriem katrs var sazaroties.

Šeit jums ir mīkla: jūs varat iegūt bezgalīgu skaitu skaitļu, sākot ar skaitli 1 un pēc tam saskaitot 5 vai reizinot ar 3. Kā mēs uzrakstām funkciju, kas, ņemot vērā skaitli, mēģina atrast šādu secību. saskaitījumi un reizinājumi, kas noved pie dotā skaitļa? Piemēram, skaitli 13 var iegūt, vispirms reizinot 1 ar 3 un pēc tam divreiz saskaitot 5. Un skaitli 15 parasti nav iespējams iegūt.

Rekursīvs risinājums:

Funkcija findSolution(target) ( funkcija find(sākums, vēsture) ( if (sākums == mērķis) atgriešanas vēsture; else if (sākt > mērķis) atgriež nulli; else return find(sākums + 5, "(" + vēsture + " + 5)") || find(sākt * 3, "(" + vēsture + " * 3)"); ) atgriezties find(1, "1"); ) console.log(findSolution(24)); // → (((1 * 3) + 5) * 3)

Šis piemērs ne vienmēr atrod īsāko risinājumu – tas apmierina jebkuru. Es negaidu, ka jūs uzreiz sapratīsit, kā programma darbojas. Bet ķersimies pie šī lieliskā rekursīvās domāšanas vingrinājuma būtības.

Iekšējās funkcijas atrašana ir rekursīva. Tam nepieciešami divi argumenti — pašreizējais skaitlis un virkne, kas satur ierakstu par to, kā mēs nonācām pie šī skaitļa. Un atgriež vai nu virkni, kas parāda mūsu darbību secību, vai nulli.

Lai to izdarītu, funkcija veic vienu no trim darbībām. Ja dotais skaitlis ir vienāds ar mērķi, tad pašreizējā vēsture ir tikai veids, kā to sasniegt, tāpēc tas tiek atgriezts. Ja dotais skaitlis ir lielāks par mērķi, nav jēgas turpināt reizināšanu un saskaitīšanu, jo tādā veidā tas tikai palielināsies. Un, ja mēs vēl neesam sasnieguši mērķi, funkcija izmēģina abus iespējamos ceļus, sākot no dotā skaitļa. Viņa izsauc sevi divas reizes, vienu reizi ar katru no veidiem. Ja pirmais zvans atgriežas, nevis nulles, tas atgriežas. Pretējā gadījumā tiek atgriezta otrā.

Lai labāk saprastu, kā funkcija panāk vēlamo efektu, apskatīsim tās zvanus, kas rodas, meklējot risinājumu numuram 13.

Atrast(1, "1") atrast(6, "(1 + 5)") atrast(11, "((1 + 5) + 5)") atrast(16, "((1 + 5) + 5 ) + 5)") pārāk liels atradums(33, "(((1 + 5) + 5) * 3)") pārāk liels atradums(18, "((1 + 5) * 3)") pārāk liels atradums( 3, "(1 * 3)") atrast(8, "((1 * 3) + 5)") atrast(13, "(((1 * 3) + 5) + 5)") atrasts!

Atkāpe parāda zvanu steka dziļumu. Pirmo reizi atrašanas funkcija izsauc sevi divas reizes, lai pārbaudītu risinājumus, sākot ar (1 + 5) un (1 * 3). Pirmajā izsaukumā tiek meklēts risinājums, kas sākas ar (1 + 5), un tiek izmantota rekursija, lai pārbaudītu visus risinājumus, kas dod skaitli, kas ir mazāks vai vienāds ar vēlamo skaitli. Neatrod un atgriež nulli. Tad operators || un pāriet uz funkcijas izsaukumu, kas pārbauda opciju (1 * 3). Šeit mums ir paveicies, jo trešajā rekursīvajā izsaukumā mēs iegūstam 13. Šis izsaukums atgriež virkni, un katrs no || pa ceļam nodod šo virkni augstāk, kā rezultātā atgriežot risinājumu.

Augšanas funkcijas

Ir divi vairāk vai mazāk dabiski veidi, kā programmā ieviest funkcijas.

Pirmkārt, jums ir jāraksta līdzīgs kods vairākas reizes. No tā vajadzētu izvairīties – vairāk koda nozīmē vairāk vietas kļūdām un vairāk lasāmvielas tiem, kas cenšas saprast programmu. Tāpēc mēs izmantojam atkārtotu funkcionalitāti, piešķiram tai labu nosaukumu un ievietojam to funkcijā.

Otrs veids ir tas, ka jūs atklājat vajadzību pēc kādas jaunas funkcionalitātes, ko ir vērts ievietot atsevišķā funkcijā. Sāciet ar funkcijas nosaukumu un pēc tam ierakstiet tās pamattekstu. Varat pat sākt, rakstot kodu, kas izmanto funkciju, pirms pati funkcija ir definēta.

Tas, cik grūti jums ir nosaukt funkciju, parāda, cik labi jūs saprotat tās funkcionalitāti. Ņemsim piemēru. Mums ir jāuzraksta programma, kas izdrukā divus skaitļus, govju un cāļu skaitu fermā, kam seko vārdi "govis" un "vistas". Priekšpusē esošajiem skaitļiem jāpievieno nulles, lai katrs no tiem ieņemtu tieši trīs pozīcijas.

007 Govis 011 Vistas

Acīmredzot mums ir nepieciešama funkcija ar diviem argumentiem. Sāksim kodēt.
// printFarmInventory funkcija printFarmInventory(govis, cāļi) ( var cowString = String(govis); while (cowString.length< 3) cowString = "0" + cowString; console.log(cowString + " Коров"); var chickenString = String(chickens); while (chickenString.length < 3) chickenString = "0" + chickenString; console.log(chickenString + " Куриц"); } printFarmInventory(7, 11);

Ja virknei pievienojam .length, mēs iegūstam tās garumu. Izrādās, ka while cilpas skaitļiem pievieno sākuma nulles, līdz tiek iegūta 3 rakstzīmju virkne.

Gatavs! Bet, tiklīdz mēs gatavojamies nosūtīt kodu lauksaimniekam (kopā, protams, ar lielu čeku), viņš zvana un saka, ka viņam ir cūkas fermā, un vai mēs varam pievienot cūku skaitu. uz programmu?

Protams, tas ir iespējams. Bet, kad mēs sākam kopēt un ielīmēt kodu no šīm četrām rindiņām, mēs saprotam, ka mums ir jāapstājas un jāpadomā. Ir jābūt labākam ceļam. Mēs cenšamies uzlabot programmu:

// outputZeroPaddedWithLabel funkcija printZeroPaddedWithLabel(number, label) ( var numberString = String(skaitlis); while (numberString.length< 3) numberString = "0" + numberString; console.log(numberString + " " + label); } // вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens, pigs) { printZeroPaddedWithLabel(cows, "Коров"); printZeroPaddedWithLabel(chickens, "Куриц"); printZeroPaddedWithLabel(pigs, "Свиней"); } printFarmInventory(7, 11, 3);

Darbojas! Bet nosaukums printZeroPaddedWithLabel ir nedaudz dīvains. Tas apvieno trīs lietas – izvadi, nulles polsterējumu un etiķeti – vienā funkcijā. Tā vietā, lai visu atkārtoto fragmentu ievietotu funkcijā, izcelsim vienu jēdzienu:

// pievienot nulles funkciju zeroPad(skaitlis, platums) ( var string = String(skaitlis); while (string.length< width) string = "0" + string; return string; } // вывестиИнвентаризациюФермы function printFarmInventory(cows, chickens, pigs) { console.log(zeroPad(cows, 3) + " Коров"); console.log(zeroPad(chickens, 3) + " Куриц"); console.log(zeroPad(pigs, 3) + " Свиней"); } printFarmInventory(7, 16, 3);

Funkcija ar jauku, aprakstošu nosaukumu zeroPad padara kodu vieglāk saprotamu. Un to var izmantot daudzās situācijās, ne tikai mūsu gadījumā. Piemēram, lai parādītu formatētas tabulas ar cipariem.

Cik gudrām un daudzpusīgām funkcijām jābūt? Mēs varam uzrakstīt vienkāršu funkciju, kas papildina skaitļus ar nullēm līdz trim pozīcijām, kā arī izdomātu vispārējas nozīmes funkciju skaitļu formatēšanai, kas atbalsta daļskaitļus, negatīvus skaitļus, punktu izlīdzināšanu, pildījumu ar dažādām rakstzīmēm utt.

Labs noteikums ir pievienot tikai to funkcionalitāti, kas jums noteikti ir nepieciešama. Dažreiz ir vilinoši izveidot vispārējas nozīmes ietvarus katrai mazai vajadzībai. Pretojies viņam. Jūs nekad nepabeigsit darbu, bet vienkārši uzrakstīsit kodu ķekaru, ko neviens neizmantos.

Funkcijas un blakusparādības

Funkcijas var aptuveni iedalīt tajās, kuras tiek izsauktas to blakusparādību dēļ, un tajās, kuras tiek izsauktas, lai iegūtu kādu vērtību. Protams, ir iespējams arī apvienot šīs īpašības vienā funkcijā.

Pirmā palīgfunkcija saimniecības piemērā printZeroPaddedWithLabel tiek izsaukta virknes drukāšanas blakusefekta dēļ. Otrais, zeroPad, atgriešanās vērtības dēļ. Un tā nav nejaušība, ka otrā funkcija noder biežāk nekā pirmā. Funkcijas, kas atgriež vērtības, ir vieglāk kombinējamas savā starpā nekā funkcijas, kas rada blakusparādības.

Tīra funkcija ir īpaša veida vērtību atgriešanas funkcija, kurai ne tikai nav blakus efektu, bet arī tā nav atkarīga no pārējā koda blakusparādībām - piemēram, nedarbojas ar globāliem mainīgajiem, kurus var nejauši mainīt. kaut kur citur. Tīra funkcija, ja tiek izsaukta ar tiem pašiem argumentiem, atgriež to pašu rezultātu (un nedara neko citu), kas ir diezgan jauki. Ar viņu ir viegli strādāt. Šādas funkcijas izsaukumu var garīgi aizstāt ar tās darba rezultātu, nemainot koda nozīmi. Ja vēlaties pārbaudīt šādu funkciju, varat to vienkārši izsaukt un būt drošs, ka, ja tā darbojas šajā kontekstā, tā darbosies jebkurā. Ne tik tīras funkcijas var sniegt dažādus rezultātus atkarībā no daudziem faktoriem, un tām ir blakusparādības, kuras ir grūti pārbaudīt un ņemt vērā.

Tomēr nevajadzētu kautrēties no ne visai tīru funkciju rakstīšanas vai sākt svētu koda attīrīšanu no šādām funkcijām. Blakusparādības bieži vien ir noderīgas. Nav iespējams uzrakstīt tīru funkcijas console.log versiju, un šī funkcija ir diezgan noderīga. Dažas darbības ir vieglāk izteikt, izmantojot blakusparādības.

Rezultāts

Šajā nodaļā tika parādīts, kā uzrakstīt savas funkcijas. Ja funkcijas atslēgvārds tiek izmantots kā izteiksme, atgriež rādītāju uz funkcijas izsaukumu. Ja to izmanto kā paziņojumu, mainīgo var deklarēt, piešķirot tam funkcijas izsaukumu.

Funkciju izpratnes atslēga ir lokālas darbības jomas. Funkcijā deklarētie parametri un mainīgie ir tai lokāli, tiek atkārtoti izveidoti katru reizi, kad tā tiek izsaukta, un nav redzami no ārpuses. Funkcijas, kas deklarētas citā funkcijā, var piekļūt tās darbības jomai.

Ir ļoti noderīgi sadalīt dažādus programmas veiktos uzdevumus funkcijās. Jums nav jāatkārtojas, funkcijas padara kodu lasāmāku, sadalot to semantiskās daļās, tāpat kā grāmatas nodaļas un sadaļas palīdz sakārtot vienkāršu tekstu.

Vingrinājumi

Minimums
Iepriekšējā nodaļā tika pieminēta funkcija Math.min, kas atgriež mazāko no saviem argumentiem. Tagad mēs paši varam uzrakstīt šādu funkciju. Rakstiet funkcija min A, kas izmanto divus argumentus un atgriež mazāko no tiem.

Console.log(min(0, 10)); // → 0 konsole.log(min(0, -10)); // → -10

rekursija
Mēs esam redzējuši, ka % (atlikuma) operatoru var izmantot, lai noteiktu, vai skaitlis ir pāra (% 2). Šeit ir vēl viens veids, kā noteikt:

Nulle ir pat.
Vienība ir nepāra.
Jebkuram skaitlim N ir tāda pati paritāte kā N-2.

Uzrakstiet rekursīvu funkciju isEven saskaņā ar šiem noteikumiem. Tam ir jābūt skaitlim un jāatgriež Būla vērtība.

Pārbaudiet to uz 50 un 75. Mēģiniet dot -1. Kāpēc viņa tā uzvedas? Vai ir iespējams to kaut kā salabot?

Pārbaudiet to uz 50 un 75. Skatiet, kā tas darbojas uz -1. Kāpēc? Vai jūs varat domā kā to labot?

Console.log(isEven(50)); // → true console.log(isEven(75)); // → false console.log(isEven(-1)); // → ??

Mēs skaitam pupiņas.

Virknes rakstzīmju skaitu N var iegūt, pievienojot tai .charAt(N)("string".charAt(5)), līdzīgi kā iegūstot virknes ar .length garumu. Atgriešanas vērtība būs viena rakstzīmju virkne (piemēram, "k"). Virknes pirmajai rakstzīmei ir pozīcija 0, kas nozīmē, ka pēdējais varonis pozīcija būs string.length - 1. Citiem vārdiem sakot, divu rakstzīmju virknes garums būs 2, un tās rakstzīmju pozīcijas būs 0 un 1.

Uzrakstiet funkciju countBs, kas izmanto virkni kā argumentu un atgriež "B" rakstzīmju skaitu virknē.

Pēc tam ierakstiet funkciju countChar, kas darbojas mazliet kā countBs, izņemot to, ka tam ir nepieciešams otrs parametrs, rakstzīme, kuru mēs meklēsim virknē (nevis tikai skaitīt "B" rakstzīmju skaitu). Lai to izdarītu, pārrakstiet funkciju countBs.

Pārlēkšanas paziņojumi un izņēmumu apstrāde

Vēl viena JavaScript valodas operatoru kategorija ir lēciena operatori. Kā norāda nosaukums, šie paziņojumi liek JavaScript tulkam pāriet uz citu vietu programmas kodā. Pārtraukuma paziņojums liek tulkam pāriet uz cilpas vai cita priekšraksta beigām. Turpināšanas paziņojums liek tulkam izlaist pārējo cilpas pamattekstu, pāriet atpakaļ uz cilpas sākumu un sākt jaunu iterāciju. JavaScript ir iespēja atzīmēt priekšrakstus ar nosaukumiem, lai pārtraukuma un turpinājuma priekšrakstus varētu skaidri norādīt, kurai cilpai vai citam priekšrakstam tie pieder.

Atgriešanas paziņojums liek tulkam pāriet no izsauktās funkcijas atpakaļ uz punktu, kurā tā tika izsaukta, un atgriež izsaukuma vērtību. Metiena paziņojums rada izņēmumu un ir paredzēts darbam kopā ar try/catch/finally priekšrakstiem, kas definē koda bloku, lai apstrādātu izņēmumu. Šis ir diezgan sarežģīts lēciena priekšrakstu veids: kad notiek izņēmums, tulks pāriet uz tuvāko norobežojošo izņēmumu apstrādātāju, kas var būt tajā pašā funkcijā vai augstāks, izsauktās funkcijas atgriešanas kaudzē.

Katrs no šiem lēciena operatoriem ir sīkāk aprakstīts nākamajās apakšsadaļās.

Instrukciju etiķetes

Jebkuru paziņojumu var atzīmēt ar identifikatoru un kolu pirms tā:

identifikators: instrukcija

Atzīmējot instrukciju, jūs piešķirat tai nosaukumu, ko pēc tam var izmantot kā atsauci jebkurā programmas vietā. Varat atzīmēt jebkuru instrukciju, taču ir jēga atzīmēt tikai tādas instrukcijas, kurām ir pamatteksts, piemēram, cilpas un nosacījumu priekšraksti.

Piešķirot cilpai nosaukumu, to var izmantot pārtraukuma un turpinājuma priekšrakstos, cilpas iekšpusē, lai izietu no tās vai pārietu uz cilpas sākumu, uz nākamo iterāciju. Pārtraukuma un turpināšanas priekšraksti ir vienīgie priekšraksti JavaScript valodā, kas var saturēt iezīmes — tie tiks apspriesti sīkāk vēlāk. Tālāk ir sniegts paziņojuma while piemērs ar etiķeti un turpinājuma priekšraksts, izmantojot šo etiķeti:

Mainloop: while (token != null) ( // Programmas kods izlaists... turpināt galveno cilpu; // Pāriet uz nākamo nosauktās cilpas iterāciju )

Identifikators, ko izmanto kā priekšraksta etiķeti, var būt jebkurš derīgs JavaScript identifikators, izņemot rezervētu vārdu. Iezīmju nosaukumi ir atsevišķi no mainīgo un funkciju nosaukumiem, tāpēc kā etiķetes varat izmantot identifikatorus, kas atbilst mainīgo vai funkciju nosaukumiem.

Instrukciju etiķetes ir definētas tikai instrukcijās, uz kurām tās attiecas (un, protams, tajās ievietotajās instrukcijās). Ligzdotas instrukcijas nevar marķēt ar tādiem pašiem identifikatoriem kā tajos ietvertās instrukcijas, taču divas neatkarīgas instrukcijas var marķēt ar vienu un to pašu etiķeti. Marķētās instrukcijas var atkārtoti marķēt. Tas nozīmē, ka jebkurai instrukcijai var būt vairākas etiķetes.

pārtraukuma paziņojums

Pārtraukuma paziņojums liek nekavējoties iziet no visdziļākās cilpas vai slēdža paziņojuma. Mēs jau esam redzējuši piemērus pārtraukuma priekšraksta izmantošanai slēdža priekšrakstā. Cilpos to parasti izmanto, lai nekavējoties izietu no cilpas, ja kāda iemesla dēļ ir jāpārtrauc cilpas izpilde.

Kad cikls ir ļoti sarežģīts stāvoklis pabeigšana, bieži vien ir vieglāk īstenot šos nosacījumus ar pārtraukuma paziņojumu, nekā mēģināt tos izteikt vienā cilpas nosacījumā. Nākamajā piemērā mēģināts atrast masīva elementu ar noteiktu vērtību. Cilpa beidzas parastajā veidā, kad ir sasniegts masīva beigas, vai ar pārtraukuma paziņojumu, tiklīdz tiek atrasta vēlamā vērtība:

Var arr = ["a", "b", "c", "d", "e"], rezultāts; for (var i = 0; i

Programmā JavaScript varat norādīt etiķetes nosaukumu aiz pārtraukuma atslēgvārda (identifikators bez kola):

pārtraukums etiķetes_nosaukums;

Ja pārtraukuma priekšraksts tiek izmantots ar etiķeti, tas pāriet uz nosauktā priekšraksta beigām vai pārtrauc tā izpildi. Ja nav norādījumu ar norādīto etiķeti, mēģinājums izmantot šo pārtraukuma priekšraksta formu rada sintakses kļūdu. Nosauktam priekšrakstam nav jābūt cilpai vai pārslēgšanas priekšrakstam. Apzīmētais pārtraukuma paziņojums var "aizbēgt" no jebkura saturoša paziņojuma. Apstiprinošs paziņojums var būt pat vienkāršs paziņojumu bloks, kas ievietots krokainās iekavās, lai to atzīmētu.

Jaunrindas rakstzīmi nevar ievietot starp pārtraukuma atslēgvārdu un etiķetes nosaukumu. Tas notiek tāpēc, ka JavaScript tulks automātiski ievieto trūkstošos semikolus: ja jūs pārtraucat koda rindiņu starp pārtraukuma atslēgvārdu un etiķeti, kas tam seko, tulks pieņems, ka jūs domājāt šī operatora vienkāršo formu bez etiķetes, un pievienojat semikolu. .

Apzīmētais pārtraukuma paziņojums ir nepieciešams tikai tad, ja vēlaties pārtraukt priekšraksta izpildi, kas nav tuvākā aptverošā cilpa vai slēdža priekšraksts.

turpināt paziņojumu

Paziņojums turpināt ir līdzīgs pārtraukuma paziņojumam. Tomēr tā vietā, lai izietu no cilpas, priekšraksts turpināt sāk jaunu cilpas iterāciju. Sintakse priekšlikumam turpināt ir tikpat vienkārša kā pārtraukuma priekšraksta sintakse. Paziņojumu turpināt var izmantot arī ar etiķeti.

Paziņojumu turpināt, neatkarīgi no tā, vai tas ir bez etiķetes vai ar etiķeti, var izmantot tikai cilpas pamattekstā. Izmantojot to jebkur citur, rodas sintakses kļūda. Kad tiek izpildīts paziņojums turpināt, pašreizējā cilpas iterācija tiek pārtraukta un sākas nākamā. Priekš dažādi veidi cikli nozīmē dažādas lietas:

    Ciklā while vēlreiz tiek pārbaudīta izteiksme, kas norādīta cilpas sākumā, un, ja tā ir patiesa, cilpas pamatteksts tiek izpildīts no sākuma.

    Cilpa do/while pāriet uz cilpas beigām, kur nosacījums tiek vēlreiz pārbaudīts, pirms cilpa tiek atkārtota.

    For cilpā tiek novērtēta pieauguma izteiksme un vēlreiz tiek novērtēta testa izteiksme, lai noteiktu, vai ir jāveic nākamā iterācija.

    For/in cilpā cilpa sākas no jauna, piešķirot norādītajam mainīgajam nākamā rekvizīta nosaukumu.

Ņemiet vērā atšķirību turpinājuma priekšraksta darbībā cilpās while un for. Cilpa while atgriežas tieši savā stāvoklī, savukārt for cilpa vispirms novērtē pieauguma izteiksmi un pēc tam atgriežas stāvoklī. Nākamajā piemērā ir parādīts, kā tiek izmantots neiezīmēts turpinājuma priekšraksts, lai izietu no pašreizējās cilpas iterācijas pāra skaitļiem:

var summa = 0; // Aprēķināt nepāra skaitļu summu no 0 līdz 10 par (var i = 0; i

Paziņojumu turpināt, tāpat kā pārtraukumu, var izmantot ligzdotās cilpās tādā formā, kas ietver etiķeti, un tādā gadījumā restartētā cilpa ne vienmēr ir tā, kurā uzreiz ir priekšraksts turpināt. Tāpat kā pārtraukuma gadījumā, jaunās rindiņas starp atslēgvārdu turpināt un iezīmes nosaukumu nav atļautas.

atgriešanas paziņojums

Funkcijas izsaukums ir izteiksme, un, tāpat kā visām izteiksmēm, tai ir vērtība. Atgriešanas priekšraksts funkcijās tiek izmantots, lai noteiktu funkcijas atgriezto vērtību. Atgriešanās paziņojumu var ievietot tikai funkcijas pamattekstā. Tā klātbūtne jebkur citur ir sintakses kļūda. Kad tiek izpildīts atgriešanas priekšraksts, funkcija izsaucējai programmai atgriež izteiksmes vērtību. Piemēram:

Ja funkcijai nav atgriešanas priekšraksta, tad, kad tā tiek izsaukta, tulks pa vienam izpildīs funkcijas pamattekstā esošās instrukcijas, līdz tā sasniegs funkcijas beigas, un pēc tam atgriezīs vadību programmai, kas to izsauca. Šajā gadījumā izsaukuma izteiksme atgriezīsies nenoteikta. Atgriešanās paziņojums bieži ir pēdējā instrukcija funkcijā, bet tas ir pilnīgi neobligāts: funkcija atgriezīs vadību izsaucējai programmai, tiklīdz būs sasniegts atgriešanas priekšraksts, pat ja tam seko citi priekšraksti funkcijas pamattekstā.

Atgriešanās paziņojumu var izmantot arī bez izteiksmes, un tādā gadījumā tas vienkārši pārtrauc funkciju un atgriež zvanītājam nedefinētu. Piemēram:

Funkcija myFun(arr) ( // Ja masīvā ir negatīvi skaitļi, pārtrauciet funkciju (var i = 0; i

mest paziņojumu

Izņēmums ir signāls, kas norāda uz kāda veida izņēmuma vai kļūdas rašanos. Izņēmuma celšana (metiens) ir veids, kā signalizēt par šādu kļūdu vai izņēmumu. Noķert izņēmumu (noķert) nozīmē rīkoties ar to, t.i. veikt nepieciešamos vai piemērotos pasākumus, lai atgūtu no izņēmuma.

Programmā JavaScript izņēmumi tiek parādīti, ja rodas izpildlaika kļūda un programma to skaidri paaugstina ar metiena paziņojumu. Izņēmumi tiek uztverti, izmantojot try/catch/finally paziņojumus, kas ir aprakstīti vēlāk.

Metiena priekšrakstam ir šāda sintakse:

mest izteiksmi;

Izteiksmes rezultāts var būt jebkura veida vērtība. Metiena paziņojumam var tikt nodots numurs, kas apzīmē kļūdas kodu, vai virkne, kurā ir kļūdas ziņojuma teksts. JavaScript tulks izmet izņēmumus, izmantojot klases gadījumu kļūda viena no tās apakšklasēm, un jūs varat arī izmantot līdzīgu pieeju. Objektam Error ir rekvizīts nosaukums, kas nosaka kļūdas veidu un rekvizītu ziņa A satur virkni, kas nodota konstruktora funkcijai. Tālāk ir sniegts tādas funkcijas piemērs, kas rada kļūdu objektu, kad tiek izsaukts ar nederīgu argumentu:

// Skaitļa funkcijas faktoriāls factorial(number) ( // Ja ievades arguments nav derīga vērtība, // tiek izmests izņēmums! if (skaitlis 1; i *= skaitlis, skaitlis--); /* tukšs cilpas pamatteksts */ return i ; ) konsole.log("5! = ", faktoriāls(5)); konsole. log("-3! = ", faktoriāls(-3));

Kad tiek izmests izņēmums, JavaScript tulks nekavējoties pārtrauc parasto programmas izpildi un pāriet uz tuvāko izņēmumu apstrādātāju. Izņēmumu apstrādātāji izmanto konstruēšanas try/catch/finally nozvejas paziņojumu, kas ir aprakstīts nākamajā sadaļā.

Ja koda blokam, kurā noticis izņēmums, nav atbilstošas ​​nozvejas konstrukcijas, tulks parsē nākamo ārējo koda bloku un pārbauda, ​​vai ar to ir saistīts izņēmumu apstrādātājs. Tas turpinās, līdz tiek atrasts apstrādātājs.

Ja izņēmums tiek izmests funkcijā, kas nesatur konstrukciju try/catch/finally, lai to apstrādātu, izņēmums tiek izplatīts kodā, kas izsauca funkciju. Šādi izņēmumi tiek izplatīti, izmantojot JavaScript metožu leksisko struktūru uz augšu izsaukuma stekā. Ja izņēmuma apstrādātājs nekad netiek atrasts, izņēmums tiek uzskatīts par kļūdu un tiek ziņots lietotājam.

izmēģināt/noķert/beidzot uzbūvēt

Konstrukcija try/catch/finally īsteno JavaScript izņēmumu apstrādes mehānismu. izmēģiniet paziņojumušajā konstrukcijā vienkārši definē koda bloku, kurā tiek apstrādāti izņēmumi. Mēģināšanas blokam seko nozvejas paziņojums ar paziņojumu bloku, kas jāizsauc, ja izņēmums notiek jebkur try blokā. Aizķeršanās paziņojumam seko bloks beidzot A, kas satur kodu, kas veic pēdējās darbības un tiek garantēts, ka tā darbosies neatkarīgi no tā, kas notiek mēģinājuma blokā.

Gan noķeršanas bloks, gan beigu bloks nav obligāti, taču vismaz vienam no tiem jābūt klāt pēc mēģinājuma bloka. mēģināt, noķert un visbeidzot bloki sākas un beidzas cirtaini breketes. Šī ir obligāta sintakses daļa, un to nevar izlaist, pat ja starp tām ir tikai viens paziņojums.

Šis fragments ilustrē try/catch/finally construct sintakse un mērķi:

Mēģiniet ( // Parasti šis kods darbosies nevainojami no sākuma līdz beigām. // Bet kādā brīdī tas var radīt izņēmumu, // vai nu tieši ar metiena priekšrakstu, vai netieši, // izsaucot metodi, kas izmet izņēmums. ) catch (ex) ( // Paziņojumi šajā blokā tiek izpildīti tad un tikai tad, ja try blokā notiek izņēmums //. Šajos priekšrakstos var izmantot vietējo mainīgo ex, kas // attiecas uz Error objektu vai uz citu vērtība, kas norādīta metiena priekšrakstā. // Šis bloks var vai nu kaut kādā veidā apstrādāt izņēmumu, vai arī // to ignorēt un darīt kaut ko citu, vai arī // atmest izņēmumu ar metiena priekšrakstu. ) Visbeidzot ( // Šajā blokā ir priekšraksti kas tiek izpildīti vienmēr, neatkarīgi no tā, vai , // kas noticis try blokā Tie tiek izpildīti, ja try bloks ir beidzies: // 1) kā parasti, sasniedzot bloka beigas // 2) pārtraukuma dēļ, turpināt vai atgriešanas paziņojumi // 3) ar izņēmumu, kas apstrādāts, kā norādīts iepriekš minētajā nozvejas blokā // 4) ar nenotvertu izņēmumu, kas turpina // izplatīties uz augstākiem līmeņiem)

Ņemiet vērā, ka aiz atslēgvārda nozvejas iekavās ir norādīts identifikators. Šis identifikators ir līdzīgs funkcijas parametram. Kad tiek fiksēts izņēmums, šis parametrs tiks iestatīts uz izņēmumu (piemēram, objekts Error). Atšķirībā no parasta mainīgā, identifikators, kas saistīts ar nozvejas paziņojumu, pastāv tikai nozvejas bloka pamattekstā.

Tālāk ir sniegts reālistiskāks izmēģināšanas/ķeršanas konstrukcijas piemērs. Tas izsauc iepriekšējā piemērā definēto faktoriālo () metodi un klienta puses JavaScript prompt () un alert () metodes, lai organizētu ievadi un izvadi:

Mēģiniet ( // Pajautājiet lietotājam skaitli var n = Number(prompt("Ievadiet pozitīvu skaitli", "")); // Aprēķiniet skaitļa faktoriālu, pieņemot, // ievade ir derīga var f = factorial( n); // Drukāt rezultātu alert(n + "! = " + f); ) noķert (ex) ( // Ja dati ir nepareizi, kontrole tiks nodota šeit alert(ex); // Paziņojiet lietotājam par kļūda)

Ja lietotājs ievada negatīvu skaitli, tiks parādīts brīdinājuma ziņojums:

Šis ir testa/catch konstrukcijas piemērs bez galīgā paziņojuma. Lai gan beidzot neizmanto tik bieži kā nozveju, tas tomēr dažreiz ir noderīgs. Galīgais bloks tiek garantēts, ka tiks izpildīts, ja ir izpildīta vismaz kāda try bloka daļa, neatkarīgi no tā, kā beidzās kods try blokā. Šo līdzekli parasti izmanto, lai veiktu pēdējās darbības pēc koda izpildes mēģinājuma turpinājumā.

Parastā situācijā kontrole sasniedz try bloka beigas un pēc tam pārlec uz beigu bloku, kas veic nepieciešamās beigu darbības. Ja vadība iziet no mēģinājuma bloka atgriešanās, turpināt vai pārtraukuma paziņojuma rezultātā, pēdējais bloks tiek izpildīts, pirms vadība tiek nodota citur.

Ja mēģinājuma blokā notiek izņēmums un ir atbilstošs uztveršanas bloks, kas to apstrādā, vadība vispirms tiek nodota uztveršanas blokam un pēc tam uz pēdējo bloku. Ja nav vietējā nozvejas bloka, tad vadība vispirms pāriet uz pēdējo bloku un pēc tam pāriet uz tuvāko ārējo noķeršanas bloku, kas var tikt galā ar izņēmumu.

Ja pats pēdējais bloks nodod vadību, izmantojot atgriešanās, turpināt, pārtraukuma vai izmešanas paziņojumu vai izsaucot metodi, kas rada izņēmumu, gaidošā pārsūtīšanas komanda tiek atcelta un tiek izpildīta jauna. Piemēram, ja galīgajā blokā ir izņēmums, šis izņēmums aizstās jebkuru iepriekš izmesto izņēmumu.

Operators atgriezties pārtrauc pašreizējo funkciju un atgriež tās vērtību.

Šī interaktīvā piemēra pirmkods tiek glabāts GitHub repozitorijā. Ja vēlaties piedalīties interaktīvo piemēru projektā, lūdzu, klonējiet vietni https://github.com/mdn/interactive-examples

Sintakse

atgriezties [[izteiksme]]; izteiksme Izteiksme, kuras vērtība tiks atgriezta. Ja nav norādīts, tā vietā tiek atgriezts undefined.

Apraksts

Kad funkcijā tiek izsaukts atgriešanas paziņojums, tā izpilde apstājas. Norādītā vērtība tiek atgriezta vietā, kur funkcija tika izsaukta. Piemēram, šī funkcija atgriež sava argumenta x vērtību kvadrātā (kur x ir skaitlis):

funkcija kvadrāts(x) ( atgriešanās x * x; ) var demo = kvadrāts(3); // demonstrācijas vērtība būs 9

Ja atgriešanas vērtība nav norādīta, tā vietā tiek atgriezta undefined.

Šādas izteiksmes vienmēr pārtrauc funkcijas izpildi:

atgriešanās; atgriezt patiesu; return false; atgriezt x; atgriešanās x + y / 3;

Automātiski semikoli

function magic(x) ( return function calc(x) ( return x * 42 ); ) var answer = magic(); atbilde(1337); // 56154

Specifikācijas

Specifikācija Statuss Komentārs
ECMAScript 1st Edition (ECMA-262) Standarta sākotnējā definīcija
ECMAScript 5.1 (ECMA-262)
Standarta
ECMAScript 2015 (6. izdevums, ECMA-262)
"Atgriešanas paziņojuma" definīcija šajā specifikācijā.
Standarta
ECMAScript jaunākais melnraksts (ECMA-262)
"Atgriešanas paziņojuma" definīcija šajā specifikācijā.
Melnraksts

Pārlūka saderība

Saderības tabula šajā lapā ir ģenerēta no strukturētiem datiem. Ja vēlaties papildināt datus, lūdzu, pārbaudiet tos https://github.com/mdn/browser-compat-data repozitorijā un nosūtiet mums pieprasījumu veikt izmaiņas.

Atjauniniet saderības datus vietnē GitHub

DatoriMobilaisserveris
ChromemalaFirefoxInternet ExplorerOperasafariandroid tīmekļa skatsChrome Android ierīcēmFirefox operētājsistēmai AndroidOpera operētājsistēmai AndroidSafari operētājsistēmā iOSSamsung internetsNode.js
atgrieztiesChrome Pilns atbalsts 1 mala Pilns atbalsts 12 Firefox Pilns atbalsts 1 IE Pilns atbalsts 3 Opera Pilns atbalstssafari Pilns atbalststīmekļa skats Android Pilns atbalsts 1 Chrome Android Pilns atbalsts 18 Firefox Android Pilns atbalsts 4 OperaAndroid Pilns atbalstsSafari iOS Pilns atbalstsSamsung interneta Android Pilns atbalsts 1.0 nodejs Pilns atbalsts

Funkcijas ir viens no svarīgākajiem JavaScript koda veidošanas blokiem.

Funkcijas sastāv no komandu kopas un parasti veic vienu konkrētu uzdevumu (piemēram, skaitļu summēšana, saknes aprēķināšana utt.).

Kods, kas ievietots funkcijā, tiks izpildīts tikai pēc precīzas šīs funkcijas izsaukuma.

Funkciju deklarācija

1.Sintakse:

//Funkciju deklarācijas funkcija FunctionName(var1, var2)( Funkcijas kods ) //Funkcijas izsaukums FunctionName(var1,var2);

2. Sintakse:

//Funkciju deklarācija var functionname=function(var1, var2)(Funkcijas kods) //Funkciju izsaukums funkcijasnosaukums(var1,var2);

funkcijas nosaukums norāda funkcijas nosaukumu. Katrai lapas funkcijai ir jābūt unikālam nosaukumam. Jānorāda funkcijas nosaukums ar latīņu burtiem un nedrīkst sākties ar cipariem.

per1 Un per2 ir mainīgie vai vērtības, ko var nodot funkcijā. Katrai funkcijai var nodot neierobežotu skaitu mainīgo.

Piezīme: pat ja funkcijai netiek nodots neviens mainīgais, neaizmirstiet aiz funkcijas nosaukuma ievietot iekavas "()".

Piezīme: Funkcijas JavaScript ir reģistrjutīgas.

JavaScript funkcijas piemērs

Funkcija messageWrite() zemāk esošajā piemērā tiks izpildīta tikai pēc pogas noklikšķināšanas.

Piezīme:šajā piemērā tiek izmantots notikums onclick. JavaScript notikumi tiks detalizēti apskatīti vēlāk šajā apmācībā.



Mainīgo nodošana funkcijām

Funkcijām varat nodot neierobežotu skaitu mainīgo.

Piezīme: visas manipulācijas ar mainīgajiem funkcijās faktiski tiek veiktas nevis uz pašiem mainīgajiem, bet gan uz to kopiju, tāpēc pašu mainīgo saturs funkciju izpildes rezultātā nemainās.

/* Definējiet funkciju, kas pievienotajam mainīgajam pievieno 10 un izvada rezultātu lapā */ function plus(a)( a=a+10; document.write("Funkcijas izvade: " + a+"
"); ) var a=25; document.write("Mainīgā vērtība pirms funkcijas izsaukšanas: "+a+"
"); // Izsauciet funkciju, kas nodod to mainīgajam plus(a); document.write("Mainīgā vērtība pēc funkcijas izsaukšanas: "+a+"
");

Ātrs pārskats

Lai piekļūtu globālajam mainīgajam no funkcijas, nevis tās kopijas, izmantojiet logs.mainīgā_nosaukums.

Funkcija plus(a)( logs.a=a+10; ) var a=25; document.write("Mainīgā vērtība pirms funkcijas izsaukuma: "+a+"
"); plus(a); document.write ("Mainīgā vērtība pēc funkcijas izsaukšanas: "+a+"
");

Ātrs pārskats

atgriešanas komanda

Ar komandu atgriezties Varat atgriezt vērtības no funkcijām.



Ātrs pārskats

Iebūvētās funkcijas

Papildus lietotāja definētajām JavaScript funkcijām ir arī iebūvētās funkcijas.

Piemēram, iebūvētā funkcija irFiniteļauj pārbaudīt, vai nodotā ​​vērtība ir derīgs skaitlis.

Document.write(isFinite(40)+"
"); document.write(isFinite(-590)+"
"); document.write(isFinite(90.33)+"
"); document.write(isFinite(NaN)+"
"); document.write(isFinite("Šī ir virkne")+"
");

Ātrs pārskats

Piezīme: pilns saraksts iebūvētās JavaScript funkcijas, kuras varat atrast mūsu .

Vietējie un globālie mainīgie

Tiek izsaukti mainīgie, kas izveidoti funkcijās vietējie mainīgie. Šādiem mainīgajiem var piekļūt tikai tajās funkcijās, kurās tie tika definēti.

Pēc funkcijas koda izpildes šādi mainīgie tiek iznīcināti. Tas nozīmē, ka mainīgos ar vienādu nosaukumu var definēt dažādās funkcijās.

Tiek izsaukti mainīgie, kas izveidoti ārpus funkcijas koda globālie mainīgiešādiem mainīgajiem var piekļūt no jebkuras koda vietas.

Ja funkcijā deklarējat mainīgo bez var, tas arī kļūst globāls.

Globālie mainīgie tiek iznīcināti tikai tad, kad lapa tiek aizvērta.



Ātrs pārskats

Piezīme: kad tiek parādīts, var2 būs nulle, jo func1 darbojas vietējā var2 "versijā".

Anonīmo funkciju izmantošana

Funkcijas, kurām deklarēšanas laikā nav nosaukuma, tiek izsauktas Anonīms.

Anonīmās funkcijas pamatā deklarē nevis to turpmākajam izsaukumam no koda kā parastas funkcijas, bet gan pārejai uz citām funkcijām kā parametru.

Funkcija arrMap(arr,func)( var res=new Masīvs; for (var i=0;i ");

Ātrs pārskats

Dari pats

1. vingrinājums. Izlabojiet kļūdas tālāk norādītajā kodā.

1. vingrinājums

Izlabojiet kļūdu kodā.



2. uzdevums.

  1. Reproducējiet funkciju 1.–3. kodu, pārbaudot to darbību, nododot dažādus parametrus.
  2. Nosakiet atslēgvārdu, mijiedarbojoties ar funkciju 4.

2. uzdevums

//Izsaukt pirmo slepeno funkciju document.write(secfunc1(4,12) + "
"); // Otrās slepenās funkcijas izsaukšana document.write(secfunc2(100,10) + "
"); //Izsaukt trešo slepeno funkciju secfunc3(23,10); document.write("
"); // Ceturtās slepenās funkcijas izsaukšana secfunc4 ("p");

Lūdzu, iespējojiet JavaScript, lai izmantotu Disqus komentēšanas sistēmu.




Tops