Ablakok.  Vírusok.  Jegyzetfüzetek.  Internet.  hivatal.  Segédprogramok.  Drivers

Jump utasítások és kivételkezelés

A JavaScript nyelvi operátorok másik kategóriája az ugrás operátorok. Ahogy a neve is sugallja, ezek az utasítások arra késztetik a JavaScript értelmezőt, hogy egy másik helyre ugorjanak a programkódban. A break utasítás hatására az értelmező a ciklus vagy más utasítás végére ugrik. A folytás utasítás arra készteti az értelmezőt, hogy kihagyja a ciklustörzs többi részét, visszaugorjon a ciklus elejére, és új iterációt kezdjen. BAN BEN JavaScript lehetõség van az utasításokat névvel ellátni, így a megszakító és folytató utasítások kifejezetten jelezhetõk, hogy melyik ciklushoz vagy melyik másik utasításhoz tartoznak.

A return utasítás arra készteti az értelmezőt, hogy a meghívott függvényről visszaugorjon arra a pontra, ahol meghívták, és visszaadja a hívás értékét. A throw utasítás kivételt vet fel, és úgy tervezték, hogy a try/catch/finally utasításokkal együtt működjön, amelyek egy kódblokkot határoznak meg a kivétel kezelésére. Ez egy meglehetősen bonyolult típusú ugró utasítás: kivétel esetén az értelmező a legközelebbi bezáró kivételkezelőre ugrik, amely ugyanabban a függvényben vagy magasabb is lehet, a hívott függvény visszatérési veremében.

Ezen ugrásoperátorok mindegyikét részletesebben ismertetjük a következő alfejezetekben.

Utasítási címkék

Bármely állítás megjelölhető azonosítóval és kettősponttal előtte:

azonosító: utasítás

Amikor megcímkéz egy utasítást, akkor ad neki egy nevet, amely azután referenciaként használható bárhol a programban. Bármilyen utasítást megjelölhet, de csak akkor van értelme, ha olyan utasításokat jelöl, amelyeknek törzsük van, például ciklusokat és feltételes utasításokat.

Ha nevet adunk a ciklusnak, akkor az a break és a folytatás utasításokban használható, a cikluson belül a kilépéshez, vagy a ciklus elejére, a következő iterációra ugráshoz. A szünet és a folytatás utasítások az egyetlen utasítások a JavaScript nyelvben, amelyek címkéket tartalmazhatnak – ezeket később részletesebben tárgyaljuk. A következő példa egy while utasításra mutat be egy címkét, és egy folytatást, amely ezt a címkét használja:

Mainloop: while (token != null) ( // Programkód kimaradt... Mainloop folytatása; // Ugrás a megnevezett ciklus következő iterációjára )

Az utasításcímkeként használt azonosító bármely érvényes JavaScript azonosító lehet, kivéve fenntartott szó. A címkenevek elkülönülnek a változó- és függvénynevektől, így a változó- vagy függvényneveknek megfelelő azonosítókat használhat címkeként.

Az utasításcímkék csak azokban az utasításokban vannak meghatározva, amelyekre vonatkoznak (és természetesen a bennük lévő utasításokban). A beágyazott utasítások nem címkézhetők fel ugyanazokkal az azonosítókkal, mint az azokat tartalmazó utasítások, de két független utasítás címkézhető ugyanazzal a címkével. A felcímkézett utasítások újracímkézhetők. Vagyis minden utasításnak több címkéje is lehet.

szünet kijelentés

A break utasítás hatására a legbelső hurok vagy switch utasítás azonnal kilép. Korábban már láthattunk példákat break utasítás használatára switch utasításon belül. A ciklusokban általában a ciklusból való azonnali kilépésre használják, ha valamilyen oknál fogva meg kell szakítani a ciklus végrehajtását.

Ha egy ciklusnak nagyon összetett lezárási feltétele van, gyakran könnyebb ezeket a feltételeket break utasítással megvalósítani, mint egyetlen ciklusfeltételben kifejezni. A következő példa egy adott értékű tömbelemet próbál keresni. A ciklus a szokásos módon fejeződik be, amikor a tömb végét elérjük, vagy a break utasítással, amint a kívánt értéket megtaláljuk:

Var arr = ["a","b","c","d","e"], eredmény; for (var i = 0; i

JavaScriptben megadhatja a címke nevét a break kulcsszó után (egy kettőspont nélküli azonosító):

törés címke_neve;

Ha a break utasítást címkével együtt használják, az a megnevezett utasítás végére ugrik, vagy leállítja a végrehajtását. A megadott címkével ellátott utasítás hiányában a break utasítás ezen formájának használatára tett kísérlet szintaktikai hibát generál. A named utasításnak nem kell ciklusnak vagy switch utasításnak lennie. A címkézett break utasítás „elmenekülhet” bármely olyan utasításból, amely tartalmazza. A bezáró utasítás akár egy egyszerű mondatblokk is lehet, amelyet kapcsos kapcsos zárójelek közé zárnak, és amelyek kizárólagos célja a jelölés.

Újsor karakter nem illeszthető be a break kulcsszó és a címke neve közé. Ennek az az oka, hogy a JavaScript értelmező automatikusan beszúrja a hiányzó pontosvesszőt: ha megszakít egy kódsort a break kulcsszó és az azt követő címke között, az értelmező azt feltételezi, hogy ennek az operátornak a címke nélküli egyszerű alakjára gondol, és pontosvesszőt ad hozzá. .

A címkézett break utasítás csak akkor szükséges, ha meg akarja szakítani egy olyan utasítás végrehajtását, amely nem a legközelebbi bezáró hurok vagy kapcsoló utasítás.

nyilatkozat folytatása

A folytatódik utasítás hasonló a break utasításhoz. A ciklusból való kilépés helyett azonban a turpināt utasítás a ciklus új iterációját indítja el. A folytatódik utasítás szintaxisa ugyanolyan egyszerű, mint a break utasítás szintaxisa. A folytatás utasítás címkével is használható.

A folytatási utasítás, akár címkézetlen, akár címkézett, csak a ciklus törzsében használható. Bárhol máshol használata szintaktikai hibát eredményez. Ha egy folytatási utasítás végrehajtásra kerül, a ciklus aktuális iterációja megszakad, és a következő kezdődik. Mert különböző típusok A ciklus különböző dolgokat jelent:

    A while ciklusban a ciklus elején megadott kifejezést ismét ellenőrzi, és ha igaz, akkor a ciklus törzse elölről végrehajtásra kerül.

    A do/while ciklus a ciklus végére ugrik, ahol a feltételt ismét ellenőrzi, mielőtt a ciklus megismétlődik.

    A for ciklusban a rendszer kiértékeli a növekményes kifejezést, majd a tesztkifejezést újra kiértékeli annak meghatározására, hogy végre kell-e hajtani a következő iterációt.

    A for/in ciklusban a ciklus újraindul, és a megadott változóhoz rendeli a következő tulajdonság nevét.

Jegyezze meg a while és a for ciklusokban a folytonos utasítás viselkedésének különbségét. A while ciklus közvetlenül visszatér állapotába, és hurokhoz először kiértékeli a növekmény kifejezést, majd visszatér a feltételhez. A következő példa egy címkézetlen folytatási utasítás használatát mutatja be a páros számok ciklusának aktuális iterációjából való kilépéshez:

var összeg = 0; // Kiszámítjuk a páratlan számok összegét 0 és 10 között (var i = 0; i

A folytatási utasítás, akárcsak a break, használható beágyazott ciklusokban olyan formában, amely tartalmaz egy címkét, ebben az esetben az újraindított ciklus nem feltétlenül az, amelyik közvetlenül tartalmazza a tęsti utasítást. Ugyanúgy, mint a break esetében, a folytatás kulcsszó és a címke neve között új sorok nem megengedettek.

visszáru nyilatkozat

A függvényhívás egy kifejezés, és mint minden kifejezésnek, ennek is van értéke. A függvényeken belüli return utasítás a függvény által visszaadott érték meghatározására szolgál. A return utasítás csak egy függvény törzsébe helyezhető. A jelenléte máshol szintaktikai hiba. A return utasítás végrehajtásakor a függvény visszaadja a kifejezés értékét a hívó programnak. Például:

Ha egy függvénynek nincs return utasítása, akkor meghívásakor az interpreter egyenként hajtja végre a függvénytörzs utasításait, amíg el nem éri a függvény végét, majd visszaadja a vezérlést az azt meghívó programnak. Ebben az esetben a hívási kifejezés definiálatlanul tér vissza. A return utasítás gyakran az utolsó utasítás egy függvényben, de ez teljesen opcionális: a függvény visszaadja a vezérlést a hívó programnak, amint eléri a return utasítást, még akkor is, ha azt a függvény törzsében más utasítások követik.

A return utasítás kifejezés nélkül is használható, ilyenkor egyszerűen megszakítja a függvényt, és definiálatlanul tér vissza a hívónak. Például:

Függvény myFun(arr) ( // Ha a tömb negatív számokat tartalmaz, szakítsa meg a (var i = 0; i) függvényt

dobja kijelentés

Kivétel egy jelzés, amely valamilyen kivétel vagy hiba előfordulását jelzi. Kivétel felvetése (dobás) egy ilyen hiba vagy kivétel jelzésének módja. Kivételt elkapni (catch) azt jelenti, hogy kezeljük, pl. tegye meg a szükséges vagy megfelelő intézkedéseket a kivételből való kilábalás érdekében.

A JavaScriptben a rendszer kivételeket dob, ha futásidejű hiba történik, és ha a program kifejezetten felveti azt a throw utasítással. A kivételek a try/catch/finally utasítások segítségével érhetők el, amelyeket később ismertetünk.

A throw utasítás szintaxisa a következő:

dobja kifejezés;

Egy kifejezés eredménye bármilyen típusú érték lehet. A throw utasítás átadható a hibakódot jelző számmal vagy a hibaüzenet szövegét tartalmazó karakterlánccal. A JavaScript értelmező kivételeket dob ​​egy osztály példányának használatával hiba egyik alosztályát, és hasonló megközelítést is használhat. Az Error objektumnak van egy tulajdonsága név, amely meghatározza a hiba típusát és a tulajdonságot üzenet A konstruktor függvénynek átadott karakterláncot tartalmazó A. A következő példa egy olyan függvényre mutat be példát, amely egy Error objektumot hoz létre, ha érvénytelen argumentummal hívják meg:

// Számfüggvény faktoriálisa factorial(szám) ( // Ha a bemeneti argumentum nem érvényes érték, // kivételt dob! if (szám 1; i *= szám, szám--); /* üres ciklustörzs */ return i ; ) konzol log("5! = ", faktoriális(5)); konzol log("-3! = ", faktoriális(-3));

Kivétel esetén a JavaScript értelmező azonnal megszakítja a normál programvégrehajtást, és a legközelebbi kivételkezelőre ugrik. A kivételkezelők a try/catch/finally konstrukció catch utasítását használják, amelyet a következő részben ismertetünk.

Ha a kódblokk, amelyben a kivétel előfordult, nem rendelkezik megfelelő fogási konstrukcióval, az értelmező elemzi a következő külső kódblokkot, és ellenőrzi, hogy van-e hozzá kivételkezelő társítva. Ez addig folytatódik, amíg meg nem találják a kezelőt.

Ha egy kivételt egy olyan függvényben dobnak ki, amely nem tartalmaz try/catch/finally konstrukciót a kezeléséhez, akkor a kivétel továbbterjed a függvényt meghívó kódba. Így terjednek a kivételek a JavaScript metódusok lexikális struktúráján keresztül a hívási veremben. Ha a kivételkezelő soha nem található, a kivételt hibaként kezeli, és jelenti a felhasználónak.

próbálja meg/elkapja/végre megépíteni

A try/catch/finally konstrukció a JavaScript kivételkezelési mechanizmusát valósítja meg. próbálkozzon kijelentéssel ebben a konstrukcióban egyszerűen definiál egy kódblokkot, amelyben a kivételeket kezelik. A try blokkot követi fogási nyilatkozat utasításblokkkal, amelyet akkor kell meghívni, ha a try blokkban bárhol kivétel történik. A catch utasítást egy blokk követi végül Olyan kódot tartalmaz, amely végrehajtja a végső műveleteket, és garantáltan fut, függetlenül attól, hogy mi történik a try blokkban.

Mind a catch blokk, mind a végső blokk nem kötelező, de legalább az egyiknek jelen kell lennie a try blokk után. próbáld ki, fogd meg, végül a blokkok göndör zárójelekkel kezdődnek és végződnek. Ez a szintaxis kötelező része, és akkor sem hagyható ki, ha csak egy utasítás van köztük.

A következő részlet szemlélteti a try/catch/finally konstrukció szintaxisát és célját:

Próbáld meg ( // Normális esetben ez a kód zökkenőmentesen fut az elejétől a végéig. // De valamikor kivételt dobhat, // vagy közvetlenül a throw utasítással, vagy közvetetten, // a metódus meghívásával, amely a kivétel. ) catch (ex) ( // Az ebben a blokkban lévő utasítások akkor és csak akkor hajtódnak végre, ha kivétel történik a try blokkban //. Ezek az utasítások használhatnak egy ex helyi változót, amely // az Error objektumra vagy egy másikra hivatkozik a throw utasításban megadott érték. // Ez a blokk vagy valamilyen módon kezeli a kivételt, vagy // figyelmen kívül hagyja és valami mást csinál, vagy // dobja vissza a kivételt egy throw utasítással. ) Végül ( // Ez a blokk utasításokat tartalmaz amelyek mindig végrehajtásra kerülnek, függetlenül attól, hogy , // mi történt a try blokkban Ezek akkor futnak le, ha a try blokk véget ért: // 1) a szokásos módon, a blokk végére érve // ​​2) szünet miatt, folytatás, ill. return utasítások // 3) a fenti catch blokkban megadott kivétellel // 4) egy nem elkapott kivétellel, amely továbbra is // magasabb szintekre terjed)

Vegye figyelembe, hogy a catch kulcsszót egy azonosító követi zárójelben. Ez az azonosító hasonlít egy függvényparaméterhez. Kivétel elkapásakor ez a paraméter kivételre lesz állítva (például egy Hiba objektum). A normál változókkal ellentétben a catch utasításhoz társított azonosító csak a catch blokk törzsében létezik.

A következő egy reálisabb példa a try/catch konstrukcióra. Meghívja az előző példában definiált factorial() metódust, valamint a kliensoldali JavaScript prompt() és alert() metódusait a bemenet és a kimenet rendszerezéséhez:

Próbáld meg ( // Kérd meg a felhasználótól a számot var n = Number(prompt("Adjon meg egy pozitív számot", "")); // Számítsa ki egy szám faktoriálisát, feltételezve, hogy // a bemenet érvényes var f = factorial( n); // Az eredmény kinyomtatása alert(n + "! = " + f); ) catch (ex) ( // Ha az adatok helytelenek, a vezérlés ide kerül át alert(ex); // Értesítse a felhasználót a hiba )

Ha a felhasználó negatív számot ír be, egy figyelmeztető üzenet jelenik meg:

Ez egy példa a try/catch konstrukcióra végső utasítás nélkül. Bár végül nem használják olyan gyakran, mint a catch-et, mégis néha hasznos. Az utolsó blokk akkor garantáltan lefut, ha a try blokk legalább egy része lefutott, függetlenül attól, hogy a try blokkban lévő kód hogyan végződött. Ezt a funkciót általában a kód végrehajtása utáni utolsó műveletek végrehajtására használják a próbálkozás folytatásában.

Normál helyzetben az irányítás eléri a try blokk végét, majd a végső blokkra ugrik, amely elvégzi a szükséges végső műveleteket. Ha a vezérlő kilép egy try blokkból a return, a folytatás vagy a break utasítás eredményeként, akkor a végső blokk végrehajtásra kerül, mielőtt a vezérlést máshová adná.

Ha kivétel történik egy try blokkban, és van megfelelő fogási blokk a kezelésére, akkor a vezérlés először a catch blokkra, majd a végső blokkra kerül át. Ha nincs helyi elkapási blokk, akkor az irányítás először átmegy a legvégső blokknak, majd a legközelebbi külső fogásblokkhoz ugrik, amelyik képes kezelni a kivételt.

Ha maga a Végül blokk adja át az irányítást egy return, turpina, break vagy throw utasítással vagy egy kivételt dobó metódus meghívásával, akkor a függőben lévő átviteli parancs törlődik, és egy új parancsot hajtanak végre. Például, ha a végső blokk kivételt dob, akkor ez a kivétel minden korábban dobott kivételt felvált.

Operátor Visszatérés leállítja az aktuális függvényt és visszaadja annak értékét.

Ennek az interaktív példának a forráskódja egy GitHub-tárolóban van tárolva. Ha szeretne hozzájárulni az interaktív példák projekthez, kérjük, klónozza a https://github.com/mdn/interactive-examples

Szintaxis

return [[kifejezés]]; kifejezés Az a kifejezés, amelynek értékét a rendszer visszaadja. Ha nincs megadva, akkor helyette undefined kerül visszaadásra.

Leírás

Ha egy függvényben egy return utasítást hívunk meg, a végrehajtása leáll. A megadott érték visszakerül arra a helyre, ahol a függvényt meghívták. Például a következő függvény az argumentuma x négyzetes értékét adja vissza (ahol x egy szám):

függvény négyzet(x) ( return x * x; ) var demo = square(3); // demo értéke 9 lesz

Ha nincs megadva visszatérési érték, akkor helyette undefined kerül visszaadásra.

A következő kifejezések mindig leállítják egy függvény végrehajtását:

Visszatérés; return true; return false; vissza x; visszatérés x + y / 3;

Automatikus pontosvessző

function magic(x) ( return function calc(x) ( return x * 42 ); ) var válasz = magic(); válasz(1337); // 56154

Műszaki adatok

Leírás Állapot Egy komment
ECMAScript 1st Edition (ECMA-262) Alapértelmezett eredeti meghatározás
ECMAScript 5.1 (ECMA-262)
Alapértelmezett
ECMAScript 2015 (6. kiadás, ECMA-262)
A "visszatérési nyilatkozat" meghatározása ebben a specifikációban.
Alapértelmezett
ECMAScript legújabb vázlat (ECMA-262)
A "visszatérési nyilatkozat" meghatározása ebben a specifikációban.
Piszkozat

Böngésző kompatibilitás

Az ezen az oldalon található kompatibilitási táblázat strukturált adatokból készült. Ha hozzá szeretne járulni az adatokhoz, kérjük, nézze meg a https://github.com/mdn/browser-compat-data adattárból, és küldjön lekérést a módosításaira.

Frissítse a kompatibilitási adatokat a GitHubon

SzámítógépekMobilszerver
KrómélFirefoxinternet böngészőOperaszafariandroid webviewChrome AndroidraFirefox AndroidraOpera AndroidraSafari iOS rendszerenSamsung internetNode.js
VisszatérésKróm Teljes támogatás 1 él Teljes támogatás 12 Firefox Teljes támogatás 1 AZAZ Teljes támogatás 3 Opera Teljes támogatás Igenszafari Teljes támogatás Igenwebview android Teljes támogatás 1 Chrome Android Teljes támogatás 18 Firefox Android Teljes támogatás 4 OperaAndroid Teljes támogatás IgenSafari iOS Teljes támogatás IgenSamsung Internet Android Teljes támogatás 1.0 nodejs Teljes támogatás Igen

Az emberek azt hiszik, hogy a számítástechnika a zsenik művészete. A valóságban ennek az ellenkezője igaz – csak sokan csinálnak olyan dolgokat, amelyek egymás hegyén-hátán állnak, mintha egy falat alkotnának apró kavicsokból.

Donald Knuth

Látott már olyan függvényhívásokat, mint például az alert . A függvények a JavaScript programozás kenyerét jelentik. Nagyon népszerű az az ötlet, hogy egy program egy darabját becsomagoljuk és változóként hívjuk. Ez egy strukturáló eszköz. nagy programok, az ismétlődés csökkentése, a szubrutinok nevek hozzárendelése és az alprogramok egymástól való elkülönítése.

A függvények legkézenfekvőbb felhasználási módja egy új szótár létrehozása. A hétköznapi emberi prózához szavakat találni rossz forma. Egy programozási nyelvben ez szükséges.

Egy átlagos felnőtt oroszul beszélő körülbelül 10 000 szót tud. Egy ritka programozási nyelv 10 000 beépített parancsot tartalmaz. A programozási nyelv szókincse pedig világosabban definiált, tehát kevésbé rugalmas, mint az emberié. Ezért általában saját szavainkat kell hozzá fűznünk, hogy elkerüljük a felesleges ismétlést.

Funkció meghatározása

A függvénydefiníció egy normál változódefiníció, ahol a változó által kapott érték a függvény. Például a következő kód egy változó négyzetet határoz meg, amely egy adott szám négyzetét kiszámító függvényre utal:

var négyzet = függvény(x) ( return x * x; ); console.log(négyzet(12)); // → 144

A függvény a függvény kulcsszóval kezdődő kifejezéssel jön létre. A függvényeknek van egy sor paramétere (in ez az eset, csak x), és a függvény meghívásakor végrehajtandó utasításokat tartalmazó törzs. Egy függvény törzsét mindig kapcsos zárójelek közé zárjuk, még akkor is, ha egyetlen utasításból áll.

Egy függvénynek több paramétere is lehet, vagy egy sem. A következő példában a makeNoise-nak nincs paraméterlistája, míg a powernek kettő:

Var makeNoise = function() ( console.log("A francba!"); ); zajt csinálni(); // → Szar! var hatvány = függvény(bázis, kitevő) ( var eredmény = 1; for (var count = 0; count< exponent; count++) result *= base; return result; }; console.log(power(2, 10)); // → 1024

Egyes függvények értéket adnak vissza, például a power és a square, mások nem, mint például a makeNoise, aminek csak mellékhatása van. A return utasítás határozza meg a függvény által visszaadott értéket. Amikor a programfeldolgozás eléri ezt az utasítást, azonnal kilép a függvényből, és visszaadja ezt az értéket arra a helyre a kódban, ahonnan a függvényt hívták. return kifejezés nélkül visszatér undefined .

Paraméterek és hatókör

A függvényparaméterek olyanok, mint a változók, de kezdeti értéküket a függvény hívásakor állítják be, és nem a kódjában.

A függvények fontos tulajdonsága, hogy a függvényen belül létrehozott változók (beleértve a paramétereket is) az adott függvényen belül lokálisak. Ez azt jelenti, hogy a hatványpéldában az eredményváltozó a függvény minden meghívásakor létrejön, és ennek ezek a különálló inkarnációi semmilyen módon nem kapcsolódnak egymáshoz.

A változók ezen helye csak a függvényeken belül létrehozott paraméterekre és változókra vonatkozik. A függvényen kívül beállított változókat globális változóknak nevezzük, mert a programban végig láthatók. Az ilyen változókat egy függvényen belül is elérheti, hacsak nem deklarált azonos nevű helyi változót.

A következő kód ezt szemlélteti. Két függvényt határoz meg és hív meg, amelyek értéket rendelnek x-hez. Az első lokálisnak deklarálja, így csak a helyi változót változtatja meg. A második nem deklarál, így a függvényen belüli x-szel való munka a példa elején beállított x globális változóra vonatkozik.

var x = "kívül"; var f1 = függvény() ( var x = "f1 belsejében"; ); f1(); konzolnapló(x); // → külső var f2 = function() ( x = "f2 belsejében"; ); f2(); konzolnapló(x); // → f2 belsejében

Ez a viselkedés segít megelőzni a funkciók közötti véletlen interakciót. Ha a programban bárhol minden változót használnánk, nagyon nehéz lenne megbizonyosodni arról, hogy egy változót nem használunk különböző célokra. És ha újra használna egy változót, furcsa hatásokba ütközne, amikor a harmadik féltől származó kód összekeveri a változó értékeit. Azáltal, hogy a függvény-lokális változókat úgy kezeli, hogy azok csak a függvényen belül létezzenek, a nyelv lehetővé teszi, hogy a függvényekkel úgy dolgozzunk, mintha különálló kis univerzumok lennének, ami lehetővé teszi, hogy ne aggódjunk a teljes kód egésze miatt.

Beágyazott hatókörök

A JavaScript nem csak a globális és a lokális változók között tesz különbséget. A függvények a függvényeken belül definiálhatók, ami több lokalitási szintet eredményez.

Például a következő meglehetősen értelmetlen függvény még kettőt tartalmaz:

var landscape = function() ( var result = ""; var flat = függvény(méret) ( 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()); // → ___/""""\______/"\_

A lapos és hegyi függvények azért látják az eredményváltozót, mert azon a függvényen belül vannak, amelyben meghatározásra került. De nem látják egymás számlálóváltozóit, mert az egyik függvény változói kívül esnek a másik függvény hatókörén. A tájfüggvényen kívüli környezet pedig nem látja a függvényen belül definiált változók egyikét sem.

Röviden, minden helyi hatókörben láthatja az összes olyan hatókört, amely ezt tartalmazza. A függvényen belül elérhető változók halmazát az határozza meg, hogy a függvény a programban hol van deklarálva. A függvénydefiníciót körülvevő blokkokból minden változó látható – beleértve a főprogram legfelső szintjén meghatározottakat is. A hatókörnek ezt a megközelítését lexikálisnak nevezik.

Azok, akik más programozási nyelveket tanultak, azt gondolhatják, hogy a kapcsos zárójelekbe zárt blokkok saját helyi környezetet teremtenek. A JavaScriptben azonban csak a függvények hoznak létre hatókört. Önálló blokkokat használhat:

var valami = 1; ( var valami = 2; // Csinálj valamit valami változóval... ) // Kilépés a blokkból...

De valami a blokkon belül ugyanaz a változó, mint azon kívül. Bár az ilyen blokkok megengedettek, csak if utasításokhoz és ciklusokhoz van értelme használni őket.

Ha ez furcsának tűnik számodra, nem csak neked tűnik az. A JavaScript 1.7-es verziójában kulcsszó let , amely úgy működik, mint a var, de olyan változókat hoz létre, amelyek lokálisak bármely adott blokkra, nem csak a függvényre.

Értékként funkcionál

A függvényneveket általában a program egy részének neveként használják. Egy ilyen változó egyszer be van állítva, és nem változik. Így könnyen összetéveszthető egy függvény a nevével.

De ez két különböző dolog. A függvényhívások egyszerű változóként használhatók – például bármilyen kifejezésben felhasználhatók. Lehetőség van függvényhívás tárolására egy új változóban, paraméterként átadni egy másik függvénynek, stb. Ezenkívül a függvényhívást tároló változó közönséges változó marad, és értéke megváltoztatható:

Var launchMissiles = function(value) ( ​​missileSystem. launch("kérem!"); ); if (safeMode) launchMissiles = function(value) (/* kiadás */);

Az 5. fejezetben megvitatjuk azokat a csodálatos dolgokat, amelyek a függvényhívások más függvényeknek való átadásával érhetők el.

Funkció deklaráció

Létezik egy rövidebb változata a „var square = függvény…” kifejezésnek. A függvény kulcsszó egy utasítás elején használható:

függvény négyzet(x) ( visszatér x * x; )

Ez egy függvény deklaráció. Az utasítás definiálja a négyzet változót, és hozzárendeli az adott függvényt. Eddig minden oké. Egy ilyen definíciónak csak egy buktatója van.

Console.log("A jövő azt mondja:", future()); függvény future() ( return "MÉG NINCS repülő autónk."; )

Ez a kód akkor is működik, ha a függvény az azt használó kód alatt van deklarálva. Ennek az az oka, hogy a függvénydeklarációk nem részei a programok normál felülről lefelé történő végrehajtásának. A hatókörük tetejére „költöznek”, és az adott hatókörbe tartozó bármely kóddal meghívhatók. Ez néha kényelmes, mert a legértelmesebb sorrendben írhatja be a kódot anélkül, hogy aggódnia kellene amiatt, hogy a fenti összes funkciót meg kell adnia, hogy hol használják őket.

De mi történik, ha egy függvénydeklarációt egy feltételes blokkba vagy ciklusba helyezünk? Nem kell ezt tenned. Történelmileg a JavaScript futtatására szolgáló különböző platformok eltérően kezelték az ilyen eseteket, és a jelenlegi nyelvi szabvány ezt tiltja. Ha azt szeretné, hogy programjai következetesen fussanak, csak a többi függvényen vagy a főprogramon belül használjon függvénydeklarációkat.

Függvény példa() ( függvény a() () // Normule if (valami) ( függvény b() () // Ay-yy-yy! ) )

hívási lista
Hasznos, ha közelebbről megvizsgálja, hogyan működik a végrehajtási sorrend a függvényekkel. Íme egy egyszerű program néhány függvényhívással:

greet(who) függvény ( console.log("Szia, " + who); ) greet("Semjon"); console.log("Pokeda");

Valahogy így van feldolgozva: a greet meghívásával az átlépés a függvény elejére ugrik. Meghívja a beépített console.log függvényt, amely átveszi az irányítást, elvégzi a dolgát, és visszaadja az irányítást. Aztán eléri a köszönés végét, és visszatér arra a helyre, ahonnan hívták. A következő sor ismét meghívja a console.log fájlt.

Sematikusan ez a következőképpen ábrázolható:

Top greet console.log greet top console.log top

Mivel a függvénynek vissza kell térnie oda, ahonnan meghívták, a számítógépnek emlékeznie kell arra a környezetre, amelyből a függvényt meghívták. Egy esetben a console.log visszaváltozik üdvözlésre. Egy másikban a program végére tér vissza.

Azt a helyet, ahol a számítógép emlékszik a kontextusra, veremnek nevezzük. A függvény minden egyes meghívásakor az aktuális kontextus a verem tetejére kerül. Amikor a függvény visszatér, előugrik a legfelső kontextus a veremből, és azt használja a folytatáshoz.

A veremtárhely memóriaterületet igényel. Amikor a verem túl nagyra nő, a számítógép leállítja a végrehajtást, és például „verem túlcsordulás” vagy „túl sok rekurzió” jelenik meg. A következő kód ezt szemlélteti – egy nagyon összetett kérdést tesz fel a számítógépnek, amely végtelen ugráshoz vezet két funkció között. Pontosabban, végtelen ugrásokról lenne szó, ha a számítógépnek végtelen stackje lenne. A valóságban a verem túlcsordul.

Függvény chicken() ( return egg(); ) function egg() ( return csirke(); ) console.log(chicken() + " előbb jött."); // → ??

Választható érvek
A következő kód teljesen legális és problémamentesen fut:

Alert("Szia", ​​"Jó estét", "Szia mindenkinek!");

Hivatalosan a függvény egy argumentumot vesz fel. Amikor azonban ilyen kihívást kap, nem panaszkodik. Figyelmen kívül hagyja a többi érvet, és a „Hello” feliratot jelzi.

A JavaScript nagyon engedékeny a függvénynek átadott argumentumok számát illetően. Ha túl sokat passzol, a feleslegeseket figyelmen kívül hagyja. Túl kevés – a hiányzókhoz a meghatározatlan érték lesz hozzárendelve.

Ennek a megközelítésnek az a hátránya, hogy lehetséges - sőt valószínű - rossz számú argumentumot átadni a függvénynek, és senki sem fog panaszkodni emiatt.

Az előnye, hogy olyan függvényeket hozhat létre, amelyek opcionális argumentumokat vesznek fel. Például a hatványfüggvény következő verziójában kettővel és egy argumentummal is meghívható - az utóbbi esetben a kitevő egyenlő lesz kettővel, és a függvény négyzetként működik.

A függvény hatványa(bázis, kitevő) ( if (kitevő == meghatározatlan) kitevő = 2; var eredmény = 1; for (var count = 0; count< exponent; count++) result *= base; return result; } console.log(power(4)); // → 16 console.log(power(4, 3)); // → 64

A következő fejezetben látni fogjuk, hogyan tudja egy függvény törzse megmondani a neki átadott argumentumok pontos számát. Ez azért hasznos, mert lehetővé teszi olyan függvény létrehozását, amely tetszőleges számú argumentumot tartalmaz. Például a console.log ezt a tulajdonságot használja, és kiírja az összes neki átadott argumentumot:

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

Lezárások

A függvényhívások változóként való használatának képessége, valamint az a tény, hogy a lokális változók minden egyes függvényhíváskor újra létrejönnek, egy érdekes ponthoz vezet. Mi történik a helyi változókkal, ha egy függvény meghiúsul?

A következő példa illusztrálja ezt a problémát. Ez deklarálja a wrapValue függvényt, amely létrehoz egy helyi változót. Ezután egy függvényt ad vissza, amely beolvassa a helyi változót, és visszaadja annak értékét.

wrapValue(n) függvény ( var localVariable = n; return function() ( return localVariable; ); ) var wrap1 = wrapValue(1); var wrap2 = wrapÉrték(2); konzolnapló(wrap1()); // → 1 console.log(wrap2()); // → 2

Ez érvényes és úgy működik, ahogy kell – a változóhoz való hozzáférés megmarad. Ezenkívül ugyanannak a változónak egyidejűleg több példánya is létezhet, ami tovább erősíti azt a tényt, hogy a helyi változók minden függvényhívással újra létrejönnek.

Ezt a képességet, hogy egy helyi változó valamely példányára való hivatkozással dolgozzunk, lezárásnak nevezzük. A lokális változókat lezáró függvényt záró függvénynek nevezzük. Nemcsak a változó élettartamok miatti aggódástól szabadít meg, hanem lehetővé teszi a funkciók kreatív használatát is.

Kis változtatással a példánkat egy olyan függvényré alakítjuk, amely a számokat tetszőleges számmal megszorozza.

Függvényszorzó(tényező) ( return függvény(szám) ( visszatérési szám * faktor; ); ) var kétszer = szorzó(2); console.log(twice(5)); // → 10

A wrapValue példából már nincs szükség külön változóra, például localVariable-re. Mivel a paraméter maga egy lokális változó.

Gyakorlásra van szükség ahhoz, hogy így kezdj el gondolkodni. Jó lehetőség mentális modell - képzeljük el, hogy a függvény lefagyasztja a kódot a testében, és egy csomagba csomagolja. Ha látja a return függvényt (...) (...), gondolja úgy, mint egy vezérlőpultot egy lefagyott kódrészlethez, hogy később felhasználhassa.

Példánkban a szorzó egy lefagyott kódrészletet ad vissza, amelyet a kétszeres változóban tárolunk. Az utolsó sor meghívja a változóban található függvényt, amely aktiválja a mentett kódot (visszatérési szám * faktor;). Továbbra is hozzáfér a szorzó meghívásakor definiált faktorváltozóhoz, és hozzáfér az unfreeze (5) során átadott argumentumhoz, mint numerikus paraméterhez.

rekurzió

Egy függvény hívhatja magát, ha ügyel arra, hogy ne csorduljon túl a veremben. Az ilyen függvényt rekurzívnak nevezzük. Íme egy példa a hatványozás alternatív megvalósítására:

Függvény hatvány(bázis, kitevő) ( if (kitevő == 0) return 1; else return base * hatvány(bázis, kitevő - 1); ) console.log(hatvány(2, 3)); // → 8

A matematikusok így határozzák meg a hatványozást, és talán ez elegánsabban írja le a fogalmat, mint egy ciklus. A függvény sokszor meghívja magát különböző argumentumokkal, hogy többszörös szorzást érjen el.

Ezzel a megvalósítással azonban van egy probléma - normál JavaScript-környezetben 10-szer lassabb, mint a ciklusos verzió. A loopolás olcsóbb, mint egy függvény meghívása.

A sebesség és az elegancia dilemma meglehetősen érdekes. Van egy bizonyos szakadék az emberi és a gépi kényelem között. Bármely program felgyorsítható, ha nagyobb és bonyolultabb. A programozónak meg kell találnia a megfelelő egyensúlyt.

Az első hatványozás esetén az inelegáns ciklus meglehetősen egyszerű és egyértelmű. Nincs értelme rekurzióval helyettesíteni. Gyakran azonban olyan összetett koncepciókkal dolgoznak a programok, hogy az olvashatóság növelésével a hatékonyságot csökkenteni akarjuk.

Az alapszabály, amelyet már többször megismételtek, és amellyel teljesen egyetértek - ne aggódjon a teljesítmény miatt, amíg nem biztos abban, hogy a program lelassul. Ha igen, keresse meg a leghosszabb élettartamú alkatrészeket, és keresse meg az eleganciát a hatékonysággal.

Természetesen nem szabad azonnal figyelmen kívül hagynunk a teljesítményt. Sok esetben, mint a hatványozásnál, az elegáns megoldásokból sem kapunk sok egyszerűséget. Néha egy tapasztalt programozó azonnal látja, hogy egy egyszerű megközelítés soha nem lesz elég gyors.

Ezt azért hozom fel, mert túl sok kezdő programozó ragaszkodik a hatékonysághoz kis dolgokban is. Az eredmény nagyobb, összetettebb, és gyakran nem hibamentes. Az ilyen programok írása hosszabb ideig tart, és gyakran nem is sokkal gyorsabban működnek.

De a rekurzió nem mindig csak a hurkok kevésbé hatékony alternatívája. Néhány probléma könnyebben megoldható rekurzióval. Leggyakrabban több faág bejárásáról van szó, amelyek mindegyike elágazhat.

Íme egy találós kérdés: végtelen számú számot kaphat, kezdve az 1-gyel, majd 5-öt összeadva vagy megszorozva 3-mal. összeadások és szorzások, amelyek egy adott számhoz vezetnek? Például a 13-as számot úgy kaphatjuk meg, hogy először megszorozzuk 1-et 3-mal, majd kétszer hozzáadjuk az 5-öt. És a 15-ös számot általában lehetetlen így megszerezni.

Rekurzív megoldás:

Függvény findSolution(target) ( függvény find(start, history) ( if (start == target) return történelem; else if (start > target) return null; else return find(start + 5, "(" + előzmények + " + 5)") || find(start * 3, "(" + előzmények + " * 3)"); ) return find(1, "1"); ) console.log(findSolution(24)); // → (((1 * 3) + 5) * 3)

Ez a példa nem feltétlenül találja meg a legrövidebb megoldást – bármelyiket kielégíti. Nem várom el, hogy azonnal megértse a program működését. De térjünk rá ennek a nagyszerű rekurzív gondolkodási gyakorlatnak a végére.

A belső függvénykeresés rekurzív. Két argumentumra van szükség – az aktuális számra és egy karakterláncra, amely rögzíti, hogyan jutottunk el ehhez a számhoz. És vagy egy karakterláncot ad vissza, amely a lépéseink sorozatát mutatja, vagy nullát.

Ehhez a funkció három művelet egyikét hajtja végre. Ha a megadott szám megegyezik a céllal, akkor a jelenlegi történelem csak az elérési út, ezért visszaadják. Ha a megadott szám nagyobb, mint a cél, akkor nincs értelme folytatni a szorzást és az összeadást, mert így csak nő. Ha pedig még nem értük el a célt, akkor a függvény mindkét lehetséges utat kipróbálja a megadott számból kiindulva. Kétszer idézi meg magát, mindegyik úton egyszer. Ha az első hívás nem nullát ad vissza, akkor visszatér. Ellenkező esetben a második kerül vissza.

Hogy jobban megértsük, hogyan éri el a függvény a kívánt hatást, nézzük meg a hívásait, amelyek a 13-as szám megoldását keresik.

Find(1, "1") find(6, "(1 + 5)") find(11, "((1 + 5) + 5)") find(16, "(((1 + 5) + 5) ) + 5)") túl nagy lelet(33, "(((1 + 5) + 5) * 3)") túl nagy lelet(18, "((1 + 5) * 3)") túl nagy lelet( 3, "(1 * 3)") find(8, "((1 * 3) + 5)") find(13, "((1 * 3) + 5) + 5)") megtalálva!

A behúzás a hívási verem mélységét mutatja. Az első alkalommal a find függvény kétszer meghívja magát, hogy ellenőrizze az (1 + 5) és (1 * 3) kezdetű megoldásokat. Az első hívás egy (1 + 5)-tel kezdődő megoldást keres, és rekurzióval ellenőrzi az összes olyan megoldást, amely a kívánt számnál kisebb vagy azzal egyenlő számot eredményez. Nem találja, és nullát ad vissza. Ezután az operátor || és egy függvényhívásra ugrik, amely megvizsgálja az opciót (1 * 3). Itt szerencsénk van, mert a harmadik rekurzív hívásnál 13-at kapunk. Ez a hívás egy karakterláncot ad vissza, és mindegyik || átadja ezt a karakterláncot fent, és ennek eredményeként visszaadja a megoldást.

Funkciók növekedése

Két többé-kevésbé természetes módon lehet függvényeket bevinni egy programba.

Először is többször ír le hasonló kódot. Ezt kerülni kell – több kód több helyet jelent a hibáknak és több olvasnivalót jelent azok számára, akik megpróbálják megérteni a programot. Vegyünk tehát egy visszatérő funkcionalitást, illesszünk hozzá jó névés tedd függvénybe.

A második mód az, hogy szükség van néhány új funkcióra, amelyet érdemes külön funkcióba helyezni. Kezdje a függvény nevével, majd írja be a törzsét. Kezdheti akár a függvényt használó kód megírásával, mielőtt maga a függvény definiálná.

Hogy mennyire nehéz elnevezni egy függvényt, az mutatja, mennyire érti a funkcióját. Vegyünk egy példát. Írnunk kell egy programot, ami kiír két számot, a telepen lévő tehenek és csirkék számát, majd a „tehenek” és a „csirkék” szavakat. Az előtte lévő számokhoz nullákat kell hozzáadnia, hogy mindegyik pontosan három helyet foglaljon el.

007 Tehenek 011 Tyúkok

Nyilvánvalóan szükségünk van egy két argumentummal rendelkező függvényre. Kezdjük a kódolást.
// printFarmInventory függvény printFarmInventory(tehenek, csirkék) ( var cowString = String(tehenek); 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);

Ha egy karakterlánchoz hozzáadjuk a .length értéket, megkapjuk a hosszát. Kiderült, hogy a while ciklusok bevezető nullákat adnak a számokhoz, amíg egy 3 karakterből álló karakterláncot nem kapnak.

Kész! De amint elküldjük a kódot a gazdának (persze egy jókora csekk mellett), felhív, és közli, hogy van sertése a farmon, és hozzá tudnánk adni a sertések számát. a programhoz?

Természetesen lehetséges. De amikor elkezdjük másolni és beilleszteni a kódot ebből a négy sorból, rájövünk, hogy meg kell állnunk és gondolkodnunk kell. Biztos van jobb módszer. A programot igyekszünk javítani:

// outputZeroPaddedWithLabel függvény printZeroPaddedWithLabel(szám, címke) ( var numberString = String(szám); 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);

Művek! De a printZeroPaddedWithLabel név egy kicsit furcsa. Három dolgot egyesít - a kimenetet, a nulla kitöltést és a címkét - egyetlen funkcióban. Ahelyett, hogy a teljes ismétlődő töredéket függvénybe tömjük, emeljünk ki egy fogalmat:

// nullák függvény hozzáadása zeroPad(szám, szélesség) ( var string = String(szám); 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);

Egy szép, leíró zeroPad nevű függvény megkönnyíti a kód megértését. És sok helyzetben használható, nem csak a mi esetünkben. Például formázott táblázatok számokkal való megjelenítéséhez.

Mennyire legyenek okosak és sokoldalúak a funkciók? Írhatunk egy egyszerű függvényt, amely egy számot legfeljebb három pozícióba tölt be nullákkal, valamint egy divatos általános célú függvényt a számok formázására, amely támogatja a törteket, a negatív számokat, a pontigazítást, a különböző karakterekkel való kitöltést stb.

Jó ökölszabály, hogy csak azokat a funkciókat adjuk hozzá, amelyekre feltétlenül szükségünk van. Néha csábító az általános célú keretrendszer létrehozása minden apró szükséglethez. Ellenállj neki. Soha nem fogod befejezni a munkát, csak írj egy csomó kódot, amelyet senki sem fog használni.

Funkciók és mellékhatások

A funkciókat nagyjából fel lehet osztani azokra, amelyeket mellékhatásaik miatt hívnak meg, és olyanokra, amelyeket azért hívnak meg, hogy valamilyen értéket kapjanak. Természetesen lehetőség van ezen tulajdonságok egy függvényben történő kombinálására is.

Első segítő funkció a farm példájában a printZeroPaddedWithLabel egy mellékhatás miatt kerül meghívásra: kiír egy karakterláncot. A második, a zeroPad a visszatérési érték miatt. És nem véletlen, hogy a második funkció gyakrabban jön jól, mint az első. Az értékeket visszaadó függvények könnyebben kombinálhatók egymással, mint a mellékhatásokat okozó függvények.

A tiszta függvény az értékvisszaadó függvény egy speciális fajtája, amelynek nemcsak nincs mellékhatása, de nem is függ a kód többi részének mellékhatásaitól – például nem működik véletlenül megváltoztatható globális változókkal. valahol máshol. Egy tiszta függvény, ha ugyanazokkal az argumentumokkal hívja meg, ugyanazt az eredményt adja vissza (és nem csinál mást) - ami nagyon szép. Könnyű vele dolgozni. Egy ilyen függvény meghívása mentálisan helyettesíthető a munkájának eredményével anélkül, hogy a kód jelentése megváltozna. Ha tesztelni szeretne egy ilyen függvényt, egyszerűen meghívhatja, és biztos lehet benne, hogy ha ebben a kontextusban működik, akkor bármelyikben fog működni. A nem túl tiszta függvények számos tényezőtől függően eltérő eredményeket adhatnak, és olyan mellékhatásokkal járhatnak, amelyeket nehéz tesztelni és figyelembe venni.

Nem szabad azonban félni a nem egészen tiszta függvények írásától, és nem szabad elkezdeni a kód szent megtisztítását az ilyen függvényektől. A mellékhatások gyakran hasznosak. A console.log függvény tiszta változatát nem lehet megírni, és ez a függvény nagyon hasznos. Egyes műveletek könnyebben kifejezhetők mellékhatások segítségével.

Eredmény

Ez a fejezet megmutatta, hogyan írhat saját függvényeket. Ha a függvény kulcsszót kifejezésként használja, egy mutatót ad vissza a függvényhívásra. Ha utasításként használjuk, akkor deklarálhatunk egy változót, ha függvényhívást rendelünk hozzá.

A funkciók megértésének kulcsa a helyi hatókör. A függvényen belül deklarált paraméterek és változók lokálisak, minden meghívásakor újra létrejönnek, és kívülről nem láthatók. A másik függvényen belül deklarált függvények hozzáférhetnek a hatóköréhez.

Nagyon hasznos megosztani különböző feladatokat a program függvényekké hajtja végre. Nem kell ismételnie magát, a függvények olvashatóbbá teszik a kódot azáltal, hogy szemantikai részekre osztják fel, ugyanúgy, ahogy a könyv fejezetei és szakaszai segítik az egyszerű szöveg rendszerezését.

Feladatok

Minimális
Az előző fejezetben szóba került a Math.min függvény, amely a legkisebb argumentumát adja vissza. Most már magunk is írhatunk egy ilyen függvényt. Írjon egy min függvényt, amely két argumentumot vesz fel, és ezek közül a minimumot adja vissza.

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

rekurzió
Láttuk, hogy a % (maradvány) operátor segítségével meghatározható, hogy egy szám páros-e (% 2). Itt van egy másik módszer a meghatározására:

A nulla páros.
Az egység páratlan.
Bármely N számnak ugyanaz a paritása, mint az N-2-nek.

Írjon egy rekurzív isEven függvényt ezen szabályok szerint. Egy számot kell vennie, és logikai értéket kell visszaadnia.

Teszteld 50-en és 75-ön. Adj -1-et. Miért viselkedik így? Meg lehet valahogy javítani?

Tesztelje 50-en és 75-ön. Nézze meg, hogyan viselkedik -1-en. Miért? Tudsz gondolsz valami módot ennek orvoslására?

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

A babot számoljuk.

Egy karakterlánc N karakterszámát úgy kaphatjuk meg, hogy hozzáadjuk a .charAt(N)("string".charAt(5)) karakterláncot, hasonlóan a .length karakterlánc hosszának megszerzéséhez. A visszatérési érték egyetlen karakterlánc lesz (például "k"). A karakterlánc első karakterének pozíciója 0, ami azt jelenti, hogy az utolsó karakter pozíciója string.length - 1. Más szóval, egy kétkarakteres karakterlánc hossza 2, karakterpozíciói pedig 0 és 1 lesznek.

Írjon egy countBs függvényt, amely egy karakterláncot vesz argumentumként, és visszaadja a "B" karakterek számát a karakterláncban.

Ezután írjon egy countChar függvényt, amely kicsit úgy működik, mint a countBs, azzal a különbséggel, hogy egy második paramétert vesz igénybe, azt a karaktert, amelyet keresni fogunk a karakterláncban (ahelyett, hogy csak a "B" karakterek számát számolnánk). Ehhez írja át a countBs függvényt.

Ha hibát észlel, jelöljön ki egy szövegrészt, és nyomja meg a Ctrl + Enter billentyűket
OSSZA MEG: