• Funkce javascriptu, která vrací největší hodnotu. JavaScript: Funkce

    Poslední aktualizace: 04.09.2018

    Funkce jsou sada instrukcí, které provádějí konkrétní akci nebo vypočítají konkrétní hodnotu.

    Syntaxe definice funkce:

    Funkce název_funkce([parametr [, ...]])( // Pokyny )

    Definice funkce začíná klíčovým slovem function následovaným názvem funkce. Název funkce se řídí stejnými pravidly jako název proměnné: může obsahovat pouze čísla, písmena, podtržítka a znaky dolaru ($) a musí začínat písmenem, podtržítkem nebo znakem dolaru.

    Za názvem funkce následuje seznam parametrů v závorkách. I když funkce nemá žádné parametry, prázdné závorky prostě zmizí. Poté ve složených závorkách následuje tělo funkce obsahující sadu instrukcí.

    Pojďme definovat nejjednodušší funkci:

    Funkce display()( document.write("funkce v JavaScriptu"); )

    Tato funkce se nazývá display() . Nepotřebuje žádné parametry a vše, co dělá, je zapsání řetězce na webovou stránku.

    Pouhé definování funkce však k jejímu fungování nestačí. Ještě to musíte zavolat:

    Není nutné dávat funkcím konkrétní název. Můžete použít anonymní funkce:

    Var display = function()( // definice funkce document.write("JavaScript function"); ) display();

    Ve skutečnosti definujeme proměnnou zobrazení a přiřadíme jí odkaz na funkci. A pak je funkce volána jménem proměnné.

    Můžeme také dynamicky přiřadit funkce k proměnné:

    Function goodMorning()( document.write("Dobré ráno"); ) function goodEvening()( document.write("Dobrý večer"); ) var message = goodMorning; zpráva(); // Dobré ráno zpráva = dobrýVečer; zpráva(); // Dobrý večer

    Funkční parametry

    Zvažte předání parametrů:

    Funkce display(x)( // definice funkce var z = x * x; document.write(x + "na druhou se rovná " + z); ) display(5); // volání funkce

    Funkce zobrazení přebírá jeden parametr, x. Při volání funkce jí tedy můžeme předat hodnotu, například číslo 5, jako v tomto případě.

    Pokud funkce přijímá více parametrů, pak pomocí operátoru spread... můžeme předat sadu hodnot pro tyto parametry z pole:

    Funkce sum(a, b, c)( nechť d = a + b + c; console.log(d); ) sum(1, 2, 3); nechť nums = ; součet(...čísla);

    Ve druhém případě jsou funkci předána čísla z pole nums. Abychom však nepřenesli pouze pole jako jednu hodnotu, ale právě čísla z tohoto pole, používá se operátor spread (elipsa ...).

    Volitelné parametry

    Funkce může mít mnoho parametrů, ale některé nebo všechny parametry mohou být volitelné. Není-li pro parametry předána žádná hodnota, mají výchozí hodnotu „undefined“.

    Funkce display(x, y)( if(y === nedefinováno) y = 5; if(x === nedefinováno) x = 8; nechť z = x * y; console.log(z); ) display() ; // 40 zobrazení(6); // 30 display(6, 4) // 24

    Zde má funkce zobrazení dva parametry. Při volání funkce můžeme zkontrolovat jejich hodnoty. Zároveň při volání funkce není nutné předávat hodnoty těchto parametrů. Pro kontrolu přítomnosti hodnoty parametru se používá porovnání s hodnotou undefined.

    Existuje další způsob, jak definovat hodnotu pro výchozí parametry:

    Funkce display(x = 5, y = 10)( nechť z = x * y; console.log(z); ) display(); // 50 zobrazení(6); // 60 display(6, 4) // 24

    Pokud parametrům x a y nejsou předány žádné hodnoty, získají se jako hodnoty čísla 5 a 10. Tento způsob je stručnější a intuitivnější než srovnávání s nedefinovaným.

    V tomto případě lze odvodit výchozí hodnotu parametru představující výraz:

    Funkce display(x = 5, y = 10 + x)( nechť z = x * y; console.log(z); ) display(); // 75 zobrazení(6); // 96 zobrazení(6, 4) // 24

    V tomto případě závisí hodnota parametru y na hodnotě x.

    V případě potřeby můžeme získat všechny předané parametry prostřednictvím globálně přístupného pole argumentů:

    Funkce display()( var z = 1; for(var i=0; i

    Nezáleží přitom ani na tom, že jsme při definici funkce nezadali žádné parametry, stále je můžeme předat a získat jejich hodnoty přes pole argumentů.

    Nedefinovaný počet parametrů

    Pomocí operátoru spread můžeme naznačit, že pomocí parametru lze předat proměnný počet hodnot:

    Funkce display(sezóna, ...temps)( console.log(season); for(index in temps)( console.log(temps); ) ) display("Jaro", -2, -3, 4, 2, 5); display("Léto", 20, 23, 31);

    V tomto případě druhý parametr...temps označuje, že místo toho lze předat proměnný počet hodnot. V samotné funkci představuje temps pole předávaných hodnot, které můžeme získat. Navzdory tomu však při volání funkce není předáváno pole, ale jednotlivé hodnoty.

    Výstup konzole:

    Jaro -2 -3 4 2 5 Léto 20 23 31

    Výsledek funkce

    Funkce může vrátit výsledek. K tomu se používá příkaz return:

    Variace = 5; varz = čtverec(y); document.write(y + " na druhou se rovná " + z); funkce square(x) ( return x * x; )

    Za příkazem return následuje hodnota, která má být vrácena z metody. V tomto případě je to druhá mocnina x.

    Po získání výsledku funkce jej můžeme přiřadit nějaké jiné proměnné:

    Varz = čtverec(y);

    Funguje jako parametry

    Funkce mohou fungovat jako parametry dalších funkcí:

    Function sum(x, y)( return x + y; ) function subtract(x, y)( return x - y; ) function operation(x, y, func)( var result = func(x, y); console. log(výsledek); ) konzole. log("Součet"); operace(10, 6, součet); // 16 console.log("Odečíst"); operace(10, 6, odečíst); // 4

    Operační funkce má tři parametry: x, y a func. func - představuje funkci a v době definování operace je jedno, o jakou funkci se bude jednat. Jediná známá věc je, že funkce func může mít dva parametry a vrátit hodnotu, která se pak zobrazí v konzole prohlížeče. Můžeme tedy definovat různé funkce (jako v tomto případě funkce součtu a odečítání) a předat je do volání funkce Operation.

    Vrácení funkce z funkce

    Jedna funkce může vrátit jinou funkci:

    Nabídka funkcí(n)( if(n==1) return function(x, y)( return x+y;) else if(n==2) return function(x, y)( return x - y;) else if(n==3) return function(x, y)( return x * y;) return undefined; ) for(var i=1; i< 5; i++){ var action = menu(i); if(action!==undefined){ var result = action(5, 4); console.log(result); } }

    V tomto případě funkce nabídky v závislosti na hodnotě, která jí byla předána, vrátí jednu ze tří funkcí nebo nedefinovanou.

    Článek ve vývoji!

    Článek, ve kterém se zamyslíme nad tím, co je funkce, a také nad tradiční (klasickou) verzí práce s ní. Kromě toho si rozebereme, jaké jsou argumenty (parametry) funkce a příkaz return.

    Co je to funkce?

    Funkce je nějaká instrukční sada, které lze pojmenovat a pak oslovujte ho tímto jménem odkudkoli v programu.

    Klasický příklad použití funkce. Webová stránka obsahuje kód JavaScript, nějaký fragment, ve kterém se to několikrát opakuje. Chcete-li se tomu vyhnout, můžete naformátujte tento úryvek jako funkci, A pak to zavolej na správných místech v kódu podle názvu této funkce. Volání této funkce bude znamenat provádění pokynů nachází se v něm.

    Jak organizovat provádění nějaké úlohy v JavaScriptu pomocí funkcí? Chcete-li to provést, obvykle uděláte něco takového:

    • rozdělit úkol na dílčí části (dílčí úkoly);
    • dílčí úkoly jsou formalizovány prostřednictvím funkcí;
    • vyvinout hlavní kód pomocí volání vytvořených funkcí.

    V důsledku toho se takový program stává strukturovanějším. Jednodušší je provádět různé změny a přidávat do něj nové funkce.

    Deklarace a volání funkce

    Operace funkcí v JavaScriptu lze rozdělit do 2 kroků:

    • oznámení (tvorba) funkcí.
    • volání (exekuce) tuto funkci.

    Deklarace funkce. Vytváření funkce v JavaScriptu začíná napsáním klíčového slova function, za kterým následuje název funkce, za nímž v případě potřeby následuje x ​​v závorkách. parametry jsou uvedeny, za kterým následují pokyny, které uzavřeno ve složených závorkách.

    // deklarace funkce someName function someName() ( alert("Zavolali jste funkci someName!"); ) JavaScript - Syntaxe deklarace funkce

    Funkce tohoto druhu v JavaScriptu se nazývají příkaz deklarace funkce. Kromě tohoto typu rozlišuje JavaScript také funkce výraz definice funkce a výraz funkce šipky .

    Složení názvu funkce se řídí stejnými pravidly jako název proměnné. Tito. může obsahovat písmena, čísla (0-9), znaky "$" a "_". Jako písmena se doporučuje používat pouze písmena anglické abecedy (a-z, A-Z). Název funkce, stejně jako název proměnné, nemůže začínat číslem.

    Funkce může mít libovolný počet parametrů nebo vůbec žádné. V každém případě jsou zahrnuty závorky. Pokud existuje více parametrů, musí být od sebe odděleny čárkou. Parametry funkcí jsou přístupné jejich jménem.

    Instrukční sada, uzavřený ve složených závorkách, je kód funkce, který bude proveden při jeho volání.

    Volání funkce. Deklarovaná funkce její vlastní nebude provedena. Aby bylo možné jej spustit, musí být volán. Funkce se volá zadáním jejího názvu a dvou závorek. Argumenty jsou v případě potřeby uvedeny v závorkách.

    // volání funkce uvedené v předchozím příkladu someName(); JavaScript - Syntaxe volání funkcí

    Je funkce v JavaScriptu objekt?

    Funkce v JavaScriptu jsou objekty. Všechno v JavaScriptu je objekt kromě šesti primitivních datových typů. A pokud je funkce objekt, pak lze odkaz na ni uložit do proměnné.

    // deklarace funkce someName function someName() ( alert("Volal jsi funkci someName!"); ) var reference = someName;

    Poté můžete funkci volat takto:

    Odkaz();

    Parametry a argumenty funkcí

    Funkční argumenty jsou hodnoty, které jsou předány funkci ve fázi jejího volání. Argumenty jsou od sebe odděleny čárkou.

    // volání funkce sayWelcome se dvěma předávanými argumenty sayWelcome("Ivan", "Ivanov"); // další volání funkce sayWelcome se dvěma argumenty sayWelcome("Peter", "Petrov");

    Funkční parametry je jedním ze způsobů, jak v JavaScriptu odkazovat na argumenty ve funkci. Parametry funkce jsou popsány ve fázi její deklarace v závorkách.

    Jinými slovy funkční parametry jsou lokální proměnné, které se vytvářejí automaticky ve fázi spouštění funkce. Jako hodnoty obdrží parametry odpovídající argumenty předané funkci během jejího volání. K parametrům se dostanete pouze uvnitř této funkce, mimo ni neexistují.

    // deklarace funkce sayWelcome, která má dva parametry function sayWelcome (userFirstName, userLastName) ( // instrukce, která zobrazí hodnoty parametrů "userFirstName" a "userLastName" konzole console.log("Welcome, " + userLastName + " " + userFirstName ); )

    V JavaScriptu při volání funkce počet argumentů nemusí být stejný jako počet parametrů. Parametry, které nebyly při volání nastaveny na hodnotu, nebudou definovány.

    Zavolejme například funkci z výše uvedeného příkladu, aniž bychom zadali jeden a dva parametry:

    // volání funkce sayWelcome a předání jednoho argumentu sayWelcome("Peter"); // Vítejte, nedefinováno Petře // volá funkci sayWelcome, aniž by jí předal argumenty sayWelcome(); // Vítejte undefined undefined

    Příklad funkce, která jednoduše zobrazí předané argumenty v konzole prohlížeče:

    // funkce deklarace funkce outputParam(param1, param2, param3) ( console.log(param1 + "; " + param2 + "; " + param3); ) // volá funkci outputParam a předá jí jiný počet parametrů outputParam(" Déšť" "Sníh","Mlha"); // Déšť; Sníh; mlha outputParam(17); // 17; nedefinovaný; undefined outputParam(24,33); // 24; 33; undefined outputParam(); // nedefinováno; nedefinovaný; nedefinováno

    Dalším způsobem, jak odkazovat na argumenty ve funkci, je použití objektu speciálních argumentů. Přístup k argumentům přes argumenty se provádí stejně jako k prvkům běžného pole, tzn. podle jejich sériových čísel. Tedy argument – ​​vám umožní získat první argument, argumenty – druhý argument atd.

    // deklarace funkce součet funkce součet(číslo1, číslo2) ( /* číslo1 nebo argumenty - získat hodnotu 1 argumentu číslo2 nebo argumenty - získat hodnotu 2 argumentů */ var suma1 = číslo1 + číslo2, součet2 = argumenty + argumenty; return "Součet, součet získaný metodou 1 je " + součet1 + "; součet získaný metodou 2 je " + součet2; ) /* výstup výsledku součtové funkce do konzole 7 - první argument (může být přístupné jak jménem num1, tak pomocí argumentů) 4 - druhý argument (lze k němu přistupovat jak jménem num2, tak argumenty) */ console.log(sum(7,4));

    Hlavní rozdíl mezi těmito metodami je v tom, že první umožňuje odkazovat pouze na ty argumenty, které dostaly jména ve fázi deklarace funkce. Druhá metoda umožňuje získat hodnotu libovolného argumentu, i když nemá název (podle sériového čísla). Tato vlastnost jazyka JavaScript umožňuje vytvářet univerzální flexibilní funkce.

    Kromě příjmu argumentů vám objekt arguments umožňuje také zjistit jejich počet. To se provádí pomocí vlastnosti length.

    Opakujte argumenty předán funkci, například pomocí cyklu for nebo for...of.

    // deklarace funkce sum function sum() ( var i = 0; console.log("Výstup všech argumentů pomocí cyklu for"); for (i; i< arguments.length; i++) { console.log(i + 1 + " аргумент равен " + arguments[i]); } console.log("Вывод всех аргументов с помощью цикла for...of"); for (arg of arguments) { console.log(arg); } } // вызов функции sum sum(7, 4, 3, 1);

    Funkce, která vypíše do konzole všechny argumenty, které jí byly předány, a jejich počet:

    // funkce deklarace funkce myFunction () ( var i; console.log("Počet předaných parametrů = " + arguments.length); // iterace přes všechny parametry pomocí cyklu for for (i = 0; i< arguments.length; i++) { console.log(i + " параметр = " + arguments[i]); } } // вызовы функции myFunction myFunction(3, 7, 27, "JavaScript"); myFunction(); myFunction("Яблоки", "Груши", "Апельсины");

    Funkce, která provádí sčítání všech jí předávaných argumentů (jejich počet není předem znám):

    // deklarace funkce var myCalc = function() ( // iterace přes všechny parametry pomocí cyklu for var i, suma = 0; for (i = 0; i lt; arguments.length; i++) ( suma += argumenty[i ] ; ) // vrátí součet jako výsledek return sum; ) // volání funkce (výstup do konzole) console.log(myCalc(4, 20, 17, -6));

    V důsledku toho lze objekt arguments implementovat do těla funkce:

    • kontrola počtu předaných argumentů;
    • zpracování libovolného počtu parametrů.

    Kromě funkce samotné mají k argumentům, které jsou jí předány během fáze volání, přístup i další funkce, které se v ní nacházejí.

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

    Výchozí hodnota parametru

    Počínaje ECMAScriptem 2015 (6) parametr funkce můžete nastavit hodnotu, kterou bude mít ve výchozím nastavení.

    Například nastavme parametr „color“ na jeho výchozí hodnotu „#009688“:

    Funkce setBGColor(color = "#009688") ( document.body.style.backgroundColor = barva; ) setBGColor(); // barva pozadí bude #009688 setBGColor("red"); // barva pozadí bude červená

    Před ECMAScript 2015 jste mohli nastavit parametr na výchozí hodnotu, například takto:

    Funkce setBGColor(color) ( color = color !== undefined ? color: "#009688"; // nastavení barvy na výchozí hodnotu "#009688" document.body.style.backgroundColor = color; )

    Zbývající parametry

    Pokud jí při volání funkce předáte více argumentů, než má parametrů, pak zbývající můžete získat pomocí tzv. zbývající parametry (ostatní patametry). Tato funkce se v jazyce objevuje od ECMAScript 2015.

    // ...nums jsou zbývající parametry, ke kterým lze v tomto případě přistupovat pomocí názvu nums function doMath(mathAction, ...nums) ( var result = 0; nums.forEach(function(value) (​switch ( mathAction) ( case "sum": výsledek += hodnota; konec; case "sumCube": výsledek += hodnota**3; konec; case "sumSquare": výsledek += hodnota**2; konec; deafult: výsledek = 0 ; ) ) ) vrátí výsledek; ) console.log(doMath("součet", 3, 4, 21, -4)); // 24 (3 + 4 + 21 + (-4)) console.log(doMath("sumSquare", 1, 4)); // 17 (1^2 + 4^2) console.log(doMath("sumCube", 3, 2, 4)); // 99 (3^3 + 2^3 + 4^3)

    návratový výpis

    Příkaz return má vrátit hodnotu nebo výsledek vyhodnocení výrazu aktuální funkce. Hodnota nebo výraz musí být oddělen od návratu mezerou. Příkaz return navíc ukončí provádění funkce, tzn. všechny pokyny po něm nebudou provedeny.

    Funkce v JavaScriptu vždy vrátí výsledek bez ohledu na to, zda je použit příkaz return nebo ne.

    // return function function sayWelcome (userFirstName, userLastName) ( if ((!userFirstName) || (!userLastName)) return "Welcome, anonymní uživatel"; else return "Welcome, " + userLastName + " " + userFirstName ; ) // deklarace proměnné osoba var osoba; // přiřadit výsledek funkce sayWelcome do proměnné person person = sayWelcome("Ivan","Ivanov"); // vypíše hodnotu proměnné do konzole console.log(person); //Instrukce, která vypíše do konzole výsledek funkce sayWelcome console.log(sayWelcome("Peter","Petrov")); //Instrukce, která vypíše do konzole výsledek funkce sayWelcome console.log(sayWelcome("Sidorov")); JavaScript - Funkce s validací parametrů

    Funkce v JavaScriptu vždy vrátí výsledek jako výsledek svého provedení, i když není explicitně definována pomocí příkazu return. Tento výsledek není definován.

    // 1. funkce, která nevrací žádnou funkci výsledku sayWelcome (userFirstName, userLastName) ( console.log("Vítejte, " + userLastName + " " + userFirstName); ) // pokuste se získat výsledek z funkce, která ano nevracet nic console .log(sayWelcome ("Ivan", "Ivanov")); // 2. funkce obsahující příkaz return bez funkce hodnoty sayDay (den) ( den = "Dnes, " + den; return; //tento příkaz nebude proveden, protože přichází po příkazu return console.log(day) ; ) // pokuste se získat výsledek funkce, která obsahuje příkaz return bez hodnoty console.log(sayDay("21. února 2016")); JavaScript – Získejte hodnotu z funkce, která nic nevrací

    Stejný výsledek bude získán, pokud návratová hodnota není zadána pro příkaz return.

    Přetížení funkcí v JavaScriptu

    Přetížení funkcí v programování je schopnost deklarovat více funkcí se stejným názvem ve stejném rozsahu. Takové funkce se od sebe liší typem a počtem argumentů. Každá funkce má svou vlastní programovací logiku. Přetížení funkcí se používá k tomu, aby bylo možné provádět podobné akce pomocí stejného názvu funkce.

    Jazyk JavaScript nepodporuje přetěžování funkcí tak, jak je implementováno, například v jazycích podobných C. Tito. v JavaScriptu nemůžete vytvořit více funkcí se stejným názvem, které jsou ve stejném oboru.

    Podobnou funkci lze implementovat v JavaScriptu pomocí následujících kroků:

    • Chcete-li zkontrolovat, zda byl argument předán nebo ne, použijte podmínku s kontrolou jeho hodnoty pro undefined .
    • Chcete-li zkontrolovat počet argumentů předávaných funkci, použijte vlastnost délky argumentů objektu.
    • Chcete-li zjistit typ předané hodnoty argumentu, použijte operátory typeof nebo instanceof.
    • Chcete-li pracovat s proměnným počtem argumentů, použijte objekt arguments.
    • Počínaje ECMAScript6 můžete zadat výchozí hodnoty pro argumenty.

    Vytvořme například funkci, kterou lze volat s jedním nebo dvěma argumenty:

    //deklarování funkce, která mění barvu pozadí prvků funkce setBgColor(bgColor,elements) ( //pokud není parametr prvků zadán při volání if (elements=== undefined) ( //potom nastavte jeho hodnotu na "div" elementy = "div"; ) // získat všechny prvky elementy = $(elements); // procházet všechny prvky a nastavit je na prvky zadané barvy pozadí. every(function()( $(this).css("background -color",bgColor) ; )); ) /*Volání funkce setBgColor s jedním parametrem. Protože 2 není zadán, pak tato funkce změní barvu pozadí všech prvků div.*/ setBgColor("zelená"); /*Volání funkce setBgColor se 2 parametry. Protože 2, pak tato funkce změní pouze barvu pozadí prvků tlačítka.*/ setBgColor("#ff0000","button");

    Udělejme nějaké změny ve výše uvedeném kódu. Konkrétně uvedeme výchozí hodnotu pro druhý parametr:

    //deklarování funkce, která mění barvu pozadí prvků //parametr prvků je standardně nastaven na "div" funkce setBgColor(bgColor,elements = "div") ( //získání prvků všech prvků = $(elements); / /iterujte všechny prvky a nastavte jim zadanou barvu pozadí elements.each(function()( $(this).css("background-color",bgColor); )); ) //volání funkce setBgColor s uvedením jednoho parametru setBgColor("zelená" ); //volání funkce setBgColor s uvedením 2 parametrů setBgColor("#ff0000","button");

    Příklad, jak implementovat "přetíženou" funkci v JavaScriptu, která počítá počet kalorií, které člověk potřebuje za den:

    // popis funkce function countCal(pohlaví, výška) ( // parametry: pohlaví (pohlaví) a výška (výška) var výsledek; if ((pohlaví === 0) || (pohlaví === "muž")) ( výsledek = (výška - 100) * 20; ) else if ((pohlaví === 1) || (pohlaví === "žena")) (výsledek = (výška - 105) * 19; ) if (výsledek) ( // argumenty - úroveň aktivity if (argumenty) ( výsledek *= argumenty; ) console.log("Počet kalorií pro normální život: " + výsledek); ) else ( console.log("Neplatné parametry"); ) ) / * volání funkce a její předání 2 argumenty (1 - "muž", lze přistupovat se jménem pohlaví a argumenty; 2 - hodnota 185, lze přistupovat s názvem pohlaví a argumenty) */ countCal("muž", 185); /* volání funkce a předání 3 parametrů, i když v popisu funkce jsou přítomny pouze 2 (v tomto případě můžete získat hodnotu 3 parametrů pouze jako argumenty) */ countCal(0, 185, 2);

    rekurze

    Rekurze je volání uvnitř těla nějaké funkce pro sebe.

    Volání funkce se obvykle provádí v závislosti na způsobu, jakým je deklarována jménem nebo prostřednictvím proměnné obsahující odkaz na tuto funkci.

    Funkce fact(n) ( if (n === 1) ( return 1; ) return fact(n-1) * n; ) console.log(fact(5)); // 120

    Funkci uvnitř jejího těla můžete volat nejen jménem, ​​ale také pomocí vlastnosti callee objektu arguments. Ale je lepší tuto vlastnost nepoužívat, protože. je to zastaralé. Kromě toho to v přísném režimu vůbec nefunguje.

    Co jsou vestavěné (standardní) funkce?

    JavaScript má obrovskou sadu vestavěných (standardních) funkcí. Tyto funkce jsou již popsány v samotném enginu prohlížeče. Téměř všechny jsou metodami jednoho nebo druhého objektu.

    Například, aby bylo možné zavolat výstrahu vestavěné funkce (metody), není nutné ji předem deklarovat. Je to již popsáno v prohlížeči. Výstražná metoda se volá zadáním názvu, závorek a argumentu uvnitř nich. Tato metoda je určena k zobrazení zprávy na obrazovce ve formě dialogového okna. Textová zpráva je převzata z hodnoty parametru této funkce.

    // vyvolání funkce alert alert("Nějaký text"); JavaScript - Volání funkce upozornění

    Vestavěná funkce popisuje všechny akce, které může provést, když je volána. Popis akcí vestavěných funkcí je programátorovi skrytý. Příkladem takových akcí je výpočet matematického výrazu a vrácení výsledku nebo manipulace s obsahem html dokumentu. Funkce může mít parametry nebo argumenty, s nimiž provádí nějakou akci. Argumenty mohou být buď , nebo .

    Volání funkce se provádí následovně:

    var a = název funkce(par1, par2, …, parN);

    js má mnoho vestavěných funkcí pro výpočet matematických výrazů. Například funkce Math.sin vrací sinus úhlu (úhel je dán v radiánech), funkce Math.sqrt vypočítá druhou odmocninu z čísla, které jí bylo předáno jako parametr a podobně.

    Vypočítejme například druhou odmocninu z 256.

    var b = Math.sqrt(256);

    Po provedení kódu jednoho ze dvou výše uvedených příkladů bude proměnná b obsahovat hodnotu 16.

    Dnes se také podíváme na dvě funkce, které vašim skriptům umožní nějakým způsobem sdělit nějaké informace okolnímu světu. Je nepravděpodobné, že je použijete při psaní skutečných projektů, ale pomohou vám při učení.

    funkce upozornění

    Tato funkce bere jako parametr textovou reprezentaci hodnoty, kterou zobrazí v matně šedém poli s tlačítkem OK. Dokud uživatel neklikne na toto tlačítko, provádění skriptu nebude pokračovat.

    funkce document.write

    Tato funkce zapíše do html dokumentu textovou reprezentaci hodnoty, která jí byla předána jako parametr. Nikdy nepoužívejte tuto metodu při psaní skriptů pro skutečné projekty, pokud samozřejmě přesně nevíte, co děláte. Pokud tuto funkci zavoláte po načtení stránky, pak s největší pravděpodobností uvidíte prázdnou stránku s textem, který zobrazilo poslední volání této funkce.

    Matematický objekt

    Tento objekt obsahuje funkce pro výpočet matematických výrazů a některých konstant. O objektech si povíme později. Abyste mohli objekt Math použít, stačí si pamatovat, že přístup k jeho vlastnostem (funkcím a konstantám) musí být zapsán Math.FunctionNameOrConstantName.

    Vlastnosti, které objekt Math obsahuje (slovo "Math" je vynecháno):

    1. Konstanty

    E 2,718281828459045
    LN10 2,302585092994046 (log natural 10)
    LN2 0,6931471805599453 (přirozený 2 logaritmus)
    LOG10E 0,4342944819032518 (logaritmus desítkové e)
    LOG2E 1,4426950408889634 (základ 2 logaritmus e)
    PI 3,141592653589793
    SQRT1_2 0,7071067811865476 (druhá odmocnina 0,5)
    SQRT2 1,4142135623730951 (druhá odmocnina ze dvou)

    2. Goniometrické funkce

    hřích - sinus
    cos - kosinus
    tan - tečna

    Úhel, který tyto funkce berou jako argument, se udává v radiánech, nikoli ve stupních. Chcete-li převést hodnotu úhlu ze stupňů na radiány, vynásobte ji Math.PI a vydělte 180. A naopak, chcete-li převést úhel z radiánů na stupně, vynásobte jej 180 a vydělte Math.PI.

    Takže 60 stupňů je π/3 radiánů, 30 stupňů je π/6 radiánů a 45 stupňů je π/4 radiánů.

    3. Inverzní goniometrické funkce

    acos - úhlový kosinus čísla tj. úhel (v radiánech), jehož kosinus je roven argumentu
    asin - arkussinus čísla tj. úhel (v radiánech), jehož sinus je roven argumentu
    atan - arkus tangens čísla tzn. úhel (v radiánech), jehož tečna se rovná argumentu
    atan2 - arkus tangens podílu dvou argumentů

    3. Další vlastnosti

    abs - číselný modul
    patro - celočíselná část čísla, "podlaha" nebo zaokrouhlení dolů. Všimněte si, že například Math.floor(-0.9) a Math.floor(-0.1) jsou -1, nikoli nula.
    strop - zaokrouhlení nahoru nebo "strop"
    exp - vrací hodnotu výrazu e x , kde x je argument funkce
    log - vrací přirozený logaritmus čísla
    pow - vezme dva argumenty a vrátí mocninu, jejíž základem je první argument a exponent je druhý.
    max - přijímá libovolný počet parametrů a vrací maximum z nich
    min - přijímá libovolný počet parametrů a vrací minimum z nich
    random - vrací náhodnou hodnotu mezi 0 a 1
    kolo - zaokrouhlí číslo na jednotky
    sqrt - vypočítá druhou odmocninu čísla

    V průběhu následujících lekcí se budeme zabývat mnoha dalšími vestavěnými funkcemi, ale to je pro dnešek vše.

    24. května 2011 v 01:13

    Pět způsobů volání funkce

    • JavaScript
    • Překlad

    Často se setkávám s kódem JavaScript, kde jsou chyby způsobeny nepochopením toho, jak funkce v JavaScriptu fungují (mimochodem, velkou část tohoto kódu jsem napsal já). JavaScript je multiparadigmatický jazyk a má mechanismy pro funkcionální programování. Je čas prozkoumat tyto možnosti. V tomto článku vás provedu pěti způsoby volání funkcí v JavaScriptu.

    V raných fázích učení JavaScriptu si začátečníci obvykle myslí, že funkce v něm fungují v podstatě stejným způsobem jako například v C#. Mechanismy pro volání funkcí v JavaScriptu mají ale řadu důležitých rozdílů a jejich neznalost může mít za následek chyby, které nebude snadné najít.

    Pojďme napsat jednoduchou funkci, která vrátí pole tří prvků – aktuální hodnotu this a dva argumenty předané funkci.
    function makeArray(arg1, arg2)( return [ this, arg1, arg2 ]; )

    Nejběžnější způsob: globální hovor

    Začátečníci často deklarují funkce, jak je ukázáno v příkladu výše. Volání této funkce je snadné:
    makeArray("jeden", "dva"); // => [ okno, "jeden", "dva" ]
    Počkejte. Kde se vzal objekt okna? Proč to máme stejné jako okno?

    V JavaScriptu je jedno, jestli skript běží v prohlížeči nebo jiném prostředí, vždy je definován globální objekt. Jakýkoli kód v našem skriptu, který není k ničemu „připojen“ (tj. mimo deklaraci objektu), je ve skutečnosti v kontextu globálního objektu. V našem případě makeArray není jen funkce běžící sama o sobě. MakeArray je ve skutečnosti metoda okna globálního objektu (v případě spuštění kódu v prohlížeči). Je snadné to dokázat:
    alert(typeof window.methodThatNeexistuje); // => undefined alert(typeof window.makeArray); // => funkce
    To znamená volání makeArray("jeden", "dva"); je ekvivalentní volání window.makeArray("jeden", "dva"); .

    Je mi smutno, že je to nejběžnější způsob volání funkcí, protože to znamená globální funkci. A všichni víme, že globální funkce a proměnné nejsou nejlepší formou programování. To platí zejména pro JavaScript. Vyhněte se globálním definicím a nebudete litovat.

    Pravidlo volání funkce č. 1: Pokud je funkce volána přímo, bez určení objektu (například myFunction()), bude to hodnota globálního objektu (okno v případě spuštění kódu v prohlížeči).

    Volání metody

    Vytvořme jednoduchý objekt a udělejme z něj metodu makeArray. Objekt deklarujeme pomocí doslovného zápisu a poté zavoláme naši metodu:
    // vytvoření objektu var arrayMaker = ( someProperty: "nějaká hodnota", make: makeArray ); // volání metody make() arrayMaker.make("jeden", "dva"); // => [ arrayMaker, "jeden", "dva" ] // alternativní syntaxe, použijte hranaté závorky arrayMaker["make"]("jeden", "dva"); // => [ arrayMaker, "jeden", "dva" ]
    Vidíte ten rozdíl? Hodnota toho je v tomto případě samotný objekt. Proč ne window , jako v předchozím případě, protože deklarace funkce se nezměnila? Celé tajemství je v tom, jak jsou funkce předávány v JavaScriptu. Funkce je standardní typ JavaScriptu, který je ve skutečnosti objektem, a stejně jako jakýkoli jiný objekt lze funkce předávat a kopírovat. V tomto případě jsme tak trochu zkopírovali celou funkci, včetně seznamu argumentů a těla, a přiřadili výsledný objekt vlastnosti make objektu arrayMaker. To je ekvivalentní tomuto prohlášení:
    var arrayMaker = ( someProperty: "Nějaká hodnota"; make: function (arg1, arg2) ( return [ this, arg1, arg2]; ) );
    Pravidlo volání funkce č. 2: Ve funkci volané pomocí syntaxe volání metody, jako je obj.myFunction() nebo obj["myFunction"]() , to bude obj .

    Nepochopení tohoto jednoduchého obecného principu často vede k chybám při zpracování událostí:

    Kliknutím na první tlačítko se zobrazí zpráva btn1, protože v tomto případě voláme funkci jako metodu a ta uvnitř funkce získá hodnotu objektu, kterému tato metoda patří. Kliknutím na druhé tlačítko se zobrazí okno, protože v tomto případě voláme buttonClicked přímo (tj. ne jako obj.buttonClicked()). Totéž se stane, když na tag prvku přiřadíme handler události, jako v případě třetího tlačítka. Po kliknutí na třetí tlačítko se zobrazí stejná zpráva jako u druhého.

    Při používání knihoven jako jQuery na to nemusíte myslet. jQuery se postará o přepsání této hodnoty v obslužné rutině události tak, aby tato hodnota byla prvkem, který událost vyvolal:
    // použijte jQuery $("#btn1").click(function() ( alert(this.id); // jQuery zajistí, že "toto" je tlačítko ));
    Jak jQuery dokáže změnit hodnotu tohoto? Čtěte níže.

    Další dva způsoby: apply() a call()

    Logicky, čím častěji funkce používáte, tím častěji je musíte předávat a volat v různých kontextech. Často je potřeba tuto hodnotu přepsat. Pokud si pamatujete, funkce v JavaScriptu jsou objekty. V praxi to znamená, že funkce mají předem definované metody. apply() a call() jsou dvě z nich. Umožňují vám přepsat tuto hodnotu:
    var auto = ( rok: 2008, model: "Dodge Bailout" ); makeArray.apply(auto, [ "jeden", "dva" ]); // => [ auto, "jeden", "dva" ] makeArray.call(auto, "jedno", "dva"); // => [ auto, "jeden", "dva" ]
    Tyto dvě metody jsou velmi podobné. První parametr toto přepíše. Rozdíly mezi těmito dvěma jsou v následujících argumentech: Function.apply() přebírá pole hodnot, které mají být předány funkci, zatímco Function.call() bere argumenty samostatně. V praxi je podle mého názoru pohodlnější použít apply() .

    Pravidlo volání funkce č. 3: Pokud chcete tuto hodnotu přepsat bez kopírování funkce do jiného objektu, můžete použít myFunction.apply(obj) nebo myFunction.call(obj) .

    Konstruktéři

    Nebudu zabíhat do podrobností o deklarování vlastních typů v JavaScriptu, ale cítím, že je nutné vám připomenout, že v JavaScriptu neexistují žádné třídy a každý vlastní typ potřebuje konstruktor. Metody vlastního typu se také nejlépe deklarují prostřednictvím prototypu , což je vlastnost funkce konstruktoru. Vytvořme si vlastní typ:
    // deklarace funkce konstruktoru ArrayMaker(arg1, arg2) ( this.someProperty = "nezáleží na tom"; this. theArray = [ this, arg1, arg2 ]; ) // deklarace metod ArrayMaker.prototype = ( someMethod: function () ( alert( "Called someMethod"); ), getArray: function () ( return this.theArray; ) ); var am = new ArrayMaker("jeden", "dva"); var other = new ArrayMaker("první", "druhý"); am.getArray(); // => [ am, "jeden", "dva" ]
    V tomto příkladu je důležitá přítomnost operátoru new před voláním funkce. Pokud by tomu tak nebylo, bylo by to globální volání a vlastnosti vytvořené v konstruktoru by odkazovaly na globální objekt. Tohle nepotřebujeme. Konstruktory také obvykle explicitně nevracejí hodnoty. Bez operátoru new by konstruktor vrátil undefined , s ním vrátí toto . Dobrým stylem je pojmenovávat konstruktory velkým písmenem; to vám připomene potřebu nového operátora.

    Jinak bude kód uvnitř konstruktoru s největší pravděpodobností podobný kódu, který byste napsali v jiném jazyce. Hodnota tohoto je v tomto případě nový objekt, který vytváříte.

    Pravidlo volání funkce č. 4: Když je funkce volána s operátorem new, hodnota tohoto bude nový objekt vytvořený běhovým prostředím JavaScriptu. Pokud tato funkce explicitně nevrátí žádný objekt, bude vrácena implicitně.

    Závěr

    Doufejme, že pochopení rozdílu mezi různými způsoby volání funkcí vám pomůže zlepšit váš kód JavaScript. Někdy není snadné zachytit chyby související s hodnotou tohoto , takže má smysl zabránit jejich výskytu předem.

    Lidé si myslí, že informatika je umění pro génia. Ve skutečnosti je opak pravdou – jen spousta lidí dělá věci, které stojí na sobě, jako by tvořily zeď z malých oblázků.

    Donald Knuth

    Volání funkcí, jako je upozornění, jste již viděli. Funkce jsou chlebem a máslem programování v JavaScriptu. Myšlenka zabalit část programu a nazvat ji jako proměnná je velmi populární. Je to nástroj pro strukturování velkých programů, omezení opakování, přiřazování jmen podprogramům a izolování podprogramů od sebe navzájem.

    Nejviditelnější použití funkcí je vytvoření nového slovníku. Vymýšlet slova pro běžnou lidskou prózu je špatná forma. V programovacím jazyce je to nutné.

    Průměrný dospělý ruský mluvčí zná asi 10 000 slov. Vzácný programovací jazyk obsahuje 10 000 vestavěných příkazů. A slovní zásoba programovacího jazyka je jasněji definovaná, takže je méně flexibilní než lidský. Proto k němu většinou musíme přidat vlastní slova, abychom se vyhnuli zbytečnému opakování.

    Definice funkce

    Definice funkce je normální definice proměnné, kde hodnota, kterou proměnná přijímá, je funkce. Například následující kód definuje proměnnou čtverec, který odkazuje na funkci, která vypočítá druhou mocninu daného čísla:

    var square = funkce(x) ( return x * x; ); console.log(čtverec(12)); // → 144

    Funkce je vytvořena výrazem začínajícím klíčovým slovem function. Funkce mají sadu parametrů (v tomto případě pouze x) a tělo obsahující instrukce, které se mají provést při volání funkce. Tělo funkce je vždy uzavřeno ve složených závorkách, i když se skládá z jediného příkazu.

    Funkce může mít několik parametrů nebo žádný. V následujícím příkladu makeNoise nemá seznam parametrů, zatímco power má dva:

    Var makeNoise = function() ( console.log("Kurva!"); ); dělat hluk(); // → Sakra! var mocnina = funkce (základ, exponent) ( var výsledek = 1; pro (počet var = 0; počet< exponent; count++) result *= base; return result; }; console.log(power(2, 10)); // → 1024

    Některé funkce vracejí hodnotu, jako je mocnina a druhá mocnina, jiné ne, jako makeNoise, což má pouze vedlejší efekt. Příkaz return definuje hodnotu vrácenou funkcí. Když zpracování programu dosáhne této instrukce, okamžitě opustí funkci a vrátí tuto hodnotu na místo v kódu, odkud byla funkce volána. return bez výrazu vrací undefined .

    Parametry a rozsah

    Parametry funkce jsou stejné jako proměnné, ale jejich počáteční hodnoty se nastavují při volání funkce, nikoli v jejím kódu.

    Důležitou vlastností funkcí je, že proměnné vytvořené v rámci funkce (včetně parametrů) jsou v rámci této funkce lokální. To znamená, že v mocenském příkladu se proměnná result vytvoří při každém volání funkce a tyto její samostatné inkarnace spolu nijak nesouvisí.

    Tato lokalita proměnných platí pouze pro parametry a proměnné vytvořené uvnitř funkcí. Proměnné nastavené mimo jakoukoli funkci se nazývají globální proměnné, protože jsou viditelné v celém programu. K takovým proměnným můžete také přistupovat v rámci funkce, pokud jste nedeklarovali lokální proměnnou se stejným názvem.

    Následující kód to ilustruje. Definuje a volá dvě funkce, které přiřazují hodnotu x. První ji deklaruje jako lokální, čímž změní pouze lokální proměnnou. Druhý nedeklaruje, takže práce s x uvnitř funkce odkazuje na globální proměnnou x, která byla nastavena na začátku příkladu.

    var x = "venku"; var f1 = function() ( var x = "uvnitř f1"; ); f1(); konzolový log(x); // → vně var f2 = function() ( x = "uvnitř f2"; ); f2(); konzolový log(x); // → uvnitř f2

    Toto chování pomáhá zabránit náhodné interakci mezi funkcemi. Pokud by byly kdekoli v programu použity všechny proměnné, bylo by velmi obtížné zajistit, aby jedna proměnná nebyla použita pro různé účely. A pokud byste proměnnou znovu použili, narazili byste na podivné efekty, kdy si kód třetí strany pohrává s hodnotami vaší proměnné. Tím, že jazyk zachází s funkčními lokálními proměnnými tak, že existují pouze v rámci funkce, umožňuje pracovat s funkcemi, jako by to byly samostatné malé vesmíry, což vám umožňuje nestarat se o celý kód jako celek.

    Vnořené obory

    JavaScript nerozlišuje pouze mezi globálními a lokálními proměnnými. Funkce mohou být definovány v rámci funkcí, což vede k několika úrovním lokality.

    Například následující poněkud nesmyslná funkce obsahuje uvnitř další dvě:

    var landscape = function() ( var result = ""; var flat = function(size) ( 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()); // → ___/""""\______/"\_

    Funkce rovina a hora vidí výslednou proměnnou, protože jsou uvnitř funkce, ve které je definována. Nemohou však navzájem vidět početní proměnné, protože proměnné jedné funkce jsou mimo rozsah druhé. A prostředí mimo krajinnou funkci nevidí žádnou z proměnných definovaných uvnitř této funkce.

    Stručně řečeno, v každém místním rozsahu můžete vidět všechny obory, které jej obsahují. Množina proměnných dostupných uvnitř funkce je určena místem, kde je tato funkce v programu deklarována. Všechny proměnné z bloků obklopujících definici funkce jsou viditelné – včetně těch, které jsou definovány na nejvyšší úrovni v hlavním programu. Tento přístup k oborům se nazývá lexikální.

    Lidé, kteří studovali jiné programovací jazyky, by si mohli myslet, že jakýkoli blok uzavřený ve složených závorkách vytváří své vlastní místní prostředí. Ale v JavaScriptu vytvářejí rozsah pouze funkce. Můžete použít samostatné bloky:

    var něco = 1; ( var něco = 2; // Udělejte něco s proměnnou něco... ) // Ukončit blok...

    Ale něco uvnitř bloku je stejná proměnná jako venku. Ačkoli jsou takové bloky povoleny, má smysl je používat pouze pro příkazy if a smyčky.

    Pokud se vám to zdá divné, zdá se to tak nejen vám. JavaScript 1.7 zavedl klíčové slovo let, které funguje jako var, ale vytváří proměnné, které jsou lokální pro jakýkoli daný blok, nejen pro funkci.

    Funguje jako hodnoty

    Názvy funkcí se obvykle používají jako název části programu. Taková proměnná je jednou nastavena a nemění se. Je tedy snadné splést si funkci s jejím názvem.

    Ale to jsou dvě různé věci. Volání funkce lze použít jako jednoduchou proměnnou – lze je například použít v libovolném výrazu. Je možné uložit volání funkce do nové proměnné, předat ji jako parametr jiné funkci a podobně. Také proměnná, která ukládá volání funkce, zůstává běžnou proměnnou a její hodnotu lze změnit:

    Var launchMissiles = function(value) (​missileSystem. launch("prosím!"); ); if (safeMode) launchMissiles = function(value) (/* release */);

    V kapitole 5 probereme úžasné věci, které lze provést předáním volání funkcí jiným funkcím.

    Deklarace funkce

    Existuje kratší verze výrazu „var square = funkce…“. Klíčové slovo funkce lze použít na začátku příkazu:

    funkce square(x) ( return x * x; )

    Toto je deklarace funkce. Příkaz definuje proměnnou square a přiřadí jí danou funkci. Zatím je vše ok. V takové definici je pouze jedno úskalí.

    Console.log("Budoucnost říká:", future()); function future() ( return "STÁLE nemáme létající auta."; )

    Tento kód funguje, i když je funkce deklarována pod kódem, který ji používá. Je to proto, že deklarace funkcí nejsou součástí běžného provádění programů shora dolů. "Přesunou" se na vrchol svého rozsahu a mohou být volány jakýmkoli kódem v tomto rozsahu. To je někdy výhodné, protože můžete napsat kód v pořadí, které dává největší smysl, aniž byste se museli starat o to, abyste museli definovat všechny výše uvedené funkce, kde se používají.

    Co se ale stane, když umístíme deklaraci funkce do podmíněného bloku nebo smyčky? Nemusíte to dělat. Historicky různé platformy pro spouštění JavaScriptu řešily takové případy odlišně a současný jazykový standard to zakazuje. Pokud chcete, aby vaše programy běžely konzistentně, používejte deklarace funkcí pouze uvnitř jiných funkcí nebo hlavního programu.

    Příklad funkce() ( funkce a() () // Normule if (něco) ( funkce b() () // Ay-yy-yy! ) )

    zásobník hovorů
    Je užitečné podívat se blíže na to, jak pracuje příkaz k provedení s funkcemi. Zde je jednoduchý program s několika voláními funkcí:

    Funkce pozdrav(kdo) ( console.log("Ahoj, " + kdo); ) pozdrav("Semyon"); console.log("Pokeda");

    Zpracovává se asi takto: volání pozdravu způsobí skok na začátek funkce. Zavolá vestavěnou funkci console.log, která převezme řízení, udělá svou věc a vrátí řízení. Poté dorazí na konec pozdravu a vrátí se na místo, odkud bylo voláno. Další řádek znovu volá console.log.

    Schematicky to lze znázornit takto:

    Top pozdrav console.log pozdrav top console.log top

    Protože se funkce musí vrátit tam, odkud byla volána, musí si počítač pamatovat kontext, ze kterého byla funkce volána. V jednom případě by se měl console.log změnit zpět na pozdrav. V jiném se vrátí na konec programu.

    Místo, kde si počítač pamatuje kontext, se nazývá zásobník. Pokaždé, když je funkce volána, aktuální kontext se přesune na vrchol zásobníku. Když se funkce vrátí, vytáhne horní kontext ze zásobníku a použije jej k pokračování.

    Zásobník vyžaduje místo v paměti. Když se zásobník příliš zvětší, počítač přestane provádět a vydá něco jako „přetečení zásobníku“ nebo „příliš mnoho rekurze“. Následující kód to demonstruje – klade počítači velmi složitou otázku, která vede k nekonečným skokům mezi dvěma funkcemi. Přesněji by to byly nekonečné skoky, pokud by počítač měl nekonečný zásobník. Ve skutečnosti zásobník přeteče.

    Funkce chicken() ( return egg(); ) function egg() ( return chicken(); ) console.log(chicken() + "přišel jako první."); // → ??

    Nepovinné argumenty
    Následující kód je zcela legální a běží bez problémů:

    Alert("Ahoj", "Dobrý večer", "Ahoj všichni!");

    Oficiálně má funkce jeden argument. Když je však takto vyzvána, nestěžuje si. Ignoruje zbytek argumentů a zobrazí "Ahoj".

    JavaScript je velmi shovívavý k počtu argumentů předávaných funkci. Pokud projdete příliš mnoho, další budou ignorovány. Příliš málo – chybějícím bude přiřazena hodnota nedefinovaná.

    Nevýhodou tohoto přístupu je, že je možné – a dokonce pravděpodobné – předat funkci nesprávný počet argumentů a nikdo si na to nebude stěžovat.

    Výhodou je, že můžete vytvářet funkce, které přebírají volitelné argumenty. Například v další verzi mocninné funkce ji lze volat jak se dvěma, tak s jedním argumentem – v druhém případě bude exponent roven dvěma a funkce funguje jako čtverec.

    Mocnina funkce (základ, exponent) ( if (exponent == nedefinováno) exponent = 2; výsledek var = 1; pro (počet var = 0; počet< exponent; count++) result *= base; return result; } console.log(power(4)); // → 16 console.log(power(4, 3)); // → 64

    V další kapitole uvidíme, jak vám tělo funkce může říct přesný počet argumentů, které jí byly předány. To je užitečné, protože umožňuje vytvořit funkci, která přebírá libovolný počet argumentů. Například console.log používá tuto vlastnost a vytiskne všechny argumenty, které mu byly předány:

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

    Uzávěry

    Schopnost používat volání funkcí jako proměnné spolu se skutečností, že lokální proměnné jsou znovu vytvořeny pokaždé, když je funkce volána, nás přivádí k zajímavému bodu. Co se stane s lokálními proměnnými, když funkce selže?

    Následující příklad ilustruje tento problém. Deklaruje funkci wrapValue, která vytvoří lokální proměnnou. Potom vrátí funkci, která přečte tuto lokální proměnnou a vrátí její hodnotu.

    Funkce wrapValue(n) ( var localVariable = n; return function() ( return localVariable; ); ) var wrap1 = wrapValue(1); var wrap2 = wrapValue(2); log konzole(wrap1()); // → 1 console.log(wrap2()); // → 2

    To platí a funguje jak má – přístup k proměnné zůstává. Kromě toho může současně existovat více instancí stejné proměnné, což dále potvrzuje skutečnost, že místní proměnné jsou znovu vytvořeny s každým voláním funkce.

    Tato schopnost pracovat s odkazem na nějakou instanci lokální proměnné se nazývá uzavření. Funkce, která uzavírá lokální proměnné, se nazývá uzavírací funkce. Nejen, že vás zbaví starostí s proměnlivou životností, ale také vám umožní používat funkce kreativně.

    S mírnou změnou převedeme náš příklad do funkce, která násobí čísla libovolným daným číslem.

    Funkce multiplikátor(faktor) ( return function(number) ( return number * factor; ); ) var double = multiplier(2); console.log(dvakrát(5)); // → 10

    Samostatná proměnná jako localVariable z příkladu wrapValue již není potřeba. Protože parametr je sám o sobě lokální proměnnou.

    Chce to cvik, abyste začali takhle přemýšlet. Dobrou verzí mentálního modelu je představit si, že funkce zmrazí kód ve svém těle a zabalí jej do balíčku. Když uvidíte funkci return(...) (...), představte si ji jako ovládací panel pro část kódu zmrazenou pro pozdější použití.

    V našem příkladu multiplikátor vrací zmrazený kus kódu, který ukládáme do proměnné double. Poslední řádek volá funkci obsaženou v proměnné, která aktivuje uložený kód (návratové číslo * faktor;). Stále má přístup k proměnné faktor, která byla definována při volání multiplikátoru, a má také přístup k argumentu předávanému během unfreeze (5) jako číselnému parametru.

    rekurze

    Funkce se může dobře volat sama, pokud se postará o to, aby nepřetekla zásobník. Taková funkce se nazývá rekurzivní. Zde je příklad alternativní implementace umocňování:

    Funkce power(základ, exponent) ( if (exponent == 0) return 1; else return base * power(base, exponent - 1); ) console.log(power(2, 3)); // → 8

    Takto matematici definují umocňování a možná to tento koncept popisuje elegantněji než cyklus. Funkce volá sama sebe mnohokrát s různými argumenty, aby se dosáhlo vícenásobného násobení.

    Tato implementace má ale problém – v běžném prostředí JavaScriptu je 10x pomalejší než verze se smyčkou. Opakování je levnější než volání funkce.

    Dilema rychlost versus elegance je docela zajímavé. Mezi lidským pohodlím a pohodlím strojů existuje určitá propast. Jakýkoli program lze urychlit tím, že bude větší a složitější. Programátor je povinen najít správnou rovnováhu.

    V případě prvního umocňování je neelegantní smyčka docela jednoduchá a přímočará. Nemá smysl to nahrazovat rekurzí. Často však programy pracují s tak složitými koncepty, že člověk chce snížit efektivitu zvýšením čitelnosti.

    Základní pravidlo, které již bylo mnohokrát opakováno a se kterým zcela souhlasím – nestarejte se o výkon, dokud si nebudete jisti, že se program zpomaluje. Pokud ano, najděte díly, které vydrží nejdéle, a vyměňte eleganci za efektivitu tam.

    Samozřejmě bychom neměli hned úplně ignorovat výkon. V mnoha případech, stejně jako u umocňování, z elegantních řešení mnoho jednoduchosti nezískáme. Někdy zkušený programátor hned vidí, že jednoduchý přístup nebude nikdy dost rychlý.

    Uvádím to, protože příliš mnoho začínajících programátorů lpí na efektivitě i v malých věcech. Výsledek je větší, složitější a často není bez chyb. Takové programy se zapisují déle a často nepracují o moc rychleji.

    Ale rekurze není vždy jen méně efektivní alternativou smyček. Některé problémy se snáze řeší rekurzí. Nejčastěji se jedná o průchod několika větví stromu, z nichž každá se může větvit.

    Zde je hádanka pro vás: můžete získat nekonečný počet čísel, počínaje číslem 1 a pak buď sečtením 5, nebo vynásobením 3. Jak napíšeme funkci, která se při daném čísle pokusí najít posloupnost takových sčítání a násobení, které vedou k danému číslu? Například číslo 13 lze získat tak, že nejprve vynásobíte 1 3 a poté dvakrát přičtete 5. A číslo 15 je obecně nemožné takto získat.

    Rekurzivní řešení:

    Funkce findSolution(target) ( funkce find(start, historie) ( if (start == target) return history; else if (start > target) return null; else return find (start + 5, "(" + history + " + 5)") || find(start * 3, "(" + historie + " * 3)"); ) return find(1, "1"); ) console.log(findSolution(24)); // → (((1 * 3) + 5) * 3)

    Tento příklad nemusí nutně najít nejkratší řešení – vyhovuje všem. Neočekávám, že okamžitě pochopíte, jak program funguje. Pojďme ale k závěru tohoto skvělého cvičení rekurzivního myšlení.

    Vnitřní funkce find je rekurzivní. Vyžaduje dva argumenty – aktuální číslo a řetězec, který obsahuje záznam o tom, jak jsme k tomuto číslu dospěli. A vrátí buď řetězec ukazující naši sekvenci kroků, nebo hodnotu null.

    K tomu funkce provede jednu ze tří akcí. Pokud se dané číslo rovná cíli, pak současná historie je právě způsob, jak toho dosáhnout, a proto se vrací. Pokud je dané číslo větší než cíl, nemá smysl pokračovat v násobení a sčítání, protože takto se bude jen zvyšovat. A pokud jsme ještě nedosáhli cíle, funkce zkouší obě možné cesty od daného čísla. Přivolá se dvakrát, jednou každým ze způsobů. Pokud první volání nevrátí hodnotu null, vrátí se. V opačném případě se vrátí druhý.

    Abychom lépe pochopili, jak funkce dosahuje požadovaného efektu, podívejme se na její volání, která se vyskytují při hledání řešení pro číslo 13.

    Find(1; "1") find(6, "(1 + 5)") find(11, "((1 + 5) + 5)") find(16, "((1 + 5) + 5 ) + 5)") příliš velký nález(33, "(((1 + 5) + 5) * 3)") příliš velký nález(18, "((1 + 5) * 3)") příliš velký nález( 3, "(1 * 3)") najít (8, "(1 * 3) + 5)") najít (13, "(((1 * 3) + 5) + 5)") nalezeno!

    Odsazení ukazuje hloubku zásobníku volání. Poprvé se funkce find zavolá dvakrát, aby zkontrolovala řešení začínající (1 + 5) a (1 * 3). První volání hledá řešení začínající na (1 + 5) a používá rekurzi ke kontrole všech řešení, která poskytují číslo menší nebo rovné požadovanému číslu. Nenajde a vrátí hodnotu null. Potom operátor || a skočí na volání funkce, která prozkoumá možnost (1 * 3). Zde máme štěstí, protože ve třetím rekurzivním volání dostaneme 13. Toto volání vrátí řetězec a každý z || předá tento řetězec výše po cestě a ve výsledku vrátí řešení.

    Grow Functions

    Existují dva víceméně přirozené způsoby, jak zavést funkce do programu.

    Nejprve napíšete podobný kód vícekrát. Tomu je třeba se vyhnout – více kódu znamená více prostoru pro chyby a více materiálu pro čtení pro ty, kteří se snaží program pochopit. Takže vezmeme opakující se funkcionalitu, dáme jí dobré jméno a vložíme ji do funkce.

    Druhým způsobem je, že objevíte potřebu nějaké nové funkce, která stojí za to umístit do samostatné funkce. Začnete názvem funkce a poté napíšete její tělo. Můžete dokonce začít napsáním kódu, který funkci používá, ještě před tím, než je funkce samotná definována.

    Jak obtížné je pro vás funkci pojmenovat, ukazuje, jak dobře rozumíte její funkčnosti. Vezměme si příklad. Potřebujeme napsat program, který vypíše dvě čísla, počet krav a kuřat na farmě, za nimiž budou následovat slova „krávy“ a „kuřata“. K číslům vpředu musíte přidat nuly, aby každé obsadilo přesně tři pozice.

    007 Krávy 011 Slepice

    Je zřejmé, že potřebujeme funkci se dvěma argumenty. Začněme kódovat.
    // funkce printFarmInventory printFarmInventory(krávy, kuřata) ( var cowString = String(krávy); 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);

    Pokud k řetězci přidáme .length, dostaneme jeho délku. Ukázalo se, že smyčky while přidávají k číslům úvodní nuly, dokud nedostanou řetězec 3 znaků.

    Připraveno! Ale jakmile se chystáme poslat kód farmáři (samozřejmě spolu s tučnou kontrolou), zavolá a řekne nám, že má na farmě prasata a mohli bychom přidat výstup počtu prasat do programu?

    Samozřejmě je to možné. Ale když začneme kopírovat a vkládat kód z těchto čtyř řádků, uvědomíme si, že se musíme zastavit a přemýšlet. Musí existovat lepší způsob. Snažíme se program vylepšit:

    // outputZeroPaddedWithLabel funkce printZeroPaddedWithLabel(číslo, štítek) ( var numberString = String(číslo); 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);

    Funguje! Název printZeroPaddedWithLabel je ale trochu zvláštní. Spojuje tři věci – výstup, nulové odsazení a štítek – do jedné funkce. Místo toho, abychom celý opakující se fragment nacpali do funkce, zdůrazněme jeden koncept:

    // přidání funkce nul zeroPad(číslo, šířka) ( var string = String(číslo); 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);

    Funkce s pěkným, popisným názvem zeroPad usnadňuje pochopení kódu. A dá se použít v mnoha situacích, nejen v našem případě. Například pro zobrazení formátovaných tabulek s čísly.

    Jak chytré a všestranné by měly být funkce? Můžeme napsat jednoduchou funkci, která doplní číslo nulami až na tři pozice, stejně jako efektní univerzální funkci pro formátování čísel, která podporuje zlomky, záporná čísla, zarovnání teček, vyplnění různými znaky a tak dále.

    Dobrým pravidlem je přidat pouze funkce, které rozhodně potřebujete. Někdy je lákavé vytvořit obecné rámce pro každou malou potřebu. Odolejte mu. Nikdy nedokončíte práci, ale stačí napsat hromadu kódu, který nikdo nepoužije.

    Funkce a vedlejší účinky

    Funkce lze zhruba rozdělit na ty, které jsou volány kvůli jejich vedlejším účinkům, a ty, které jsou volány, aby získaly nějakou hodnotu. Samozřejmě je také možné tyto vlastnosti kombinovat v jedné funkci.

    První pomocná funkce v příkladu farmy, printZeroPaddedWithLabel, je volána kvůli vedlejšímu efektu tisku řetězce. Druhý, zeroPad, kvůli návratové hodnotě. A není náhoda, že druhá funkce přijde vhod častěji než ta první. Funkce, které vracejí hodnoty, se dají snáze kombinovat než funkce, které vytvářejí vedlejší efekty.

    Čistá funkce je speciální druh funkce vracející hodnotu, která nejenže nemá žádné vedlejší účinky, ale také nezávisí na vedlejších účincích zbytku kódu – například nepracuje s globálními proměnnými, které lze náhodně změnit. někde jinde. Čistá funkce, když je volána se stejnými argumenty, vrací stejný výsledek (a nedělá nic jiného) - což je docela příjemné. Je snadné s ní pracovat. Volání takové funkce může být mentálně nahrazeno výsledkem její práce, aniž by se změnil význam kódu. Když chcete takovou funkci otestovat, můžete ji jednoduše zavolat a být si jisti, že pokud funguje v tomto kontextu, bude fungovat v jakékoli. Ne tak čisté funkce mohou vracet různé výsledky v závislosti na mnoha faktorech a mají vedlejší účinky, které se obtížně testují a zohledňují.

    Člověk by se však neměl stydět psát funkce, které nejsou zcela čisté, nebo od takových funkcí zahájit posvátné čištění kódu. Vedlejší účinky jsou často užitečné. Neexistuje způsob, jak napsat čistou verzi funkce console.log a tato funkce je docela užitečná. Některé operace lze snadněji vyjádřit pomocí vedlejších účinků.

    Výsledek

    Tato kapitola vám ukázala, jak psát své vlastní funkce. Když je klíčové slovo funkce použito jako výraz, vrátí ukazatel na volání funkce. Při použití jako příkaz můžete proměnnou deklarovat tak, že k ní přiřadíte volání funkce.

    Klíčem k pochopení funkcí jsou místní rozsahy. Parametry a proměnné deklarované uvnitř funkce jsou pro ni lokální, znovu se vytvářejí při každém jejím volání a nejsou viditelné zvenčí. Funkce deklarované uvnitř jiné funkce mají přístup k jejímu rozsahu.

    Je velmi užitečné rozdělit různé úkoly prováděné programem do funkcí. Nemusíte se opakovat, funkce dělají kód čitelnějším tím, že jej rozdělují na sémantické části, stejně jako kapitoly a části knihy pomáhají organizovat prostý text.

    Cvičení

    Minimální
    V předchozí kapitole byla zmíněna funkce Math.min, která vrací nejmenší ze svých argumentů. Nyní si takovou funkci můžeme napsat sami. Napište funkci min, která vezme dva argumenty a vrátí minimum z nich.

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

    rekurze
    Viděli jsme, že operátor % (zbytek) lze použít k určení, zda je číslo sudé (% 2). Zde je další způsob, jak určit:

    Nula je sudá.
    Jednotka je lichá.
    Jakékoli číslo N má stejnou paritu jako N-2.

    Napište rekurzivní funkci isEven podle těchto pravidel. Musí vzít číslo a vrátit booleovskou hodnotu.

    Otestujte to na 50 a 75. Zkuste to dát -1. Proč se tak chová? Dá se to nějak opravit?

    Otestujte to na 50 a 75. Podívejte se, jak se chová na -1. Proč? Napadá vás způsob, jak to opravit?

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

    Počítáme fazole.

    Číslo znaku N řetězce lze získat přidáním .charAt(N)("string".charAt(5)) k němu podobným způsobem jako získání délky řetězce s .length. Vrácenou hodnotou bude jeden znakový řetězec (například "k"). První znak řetězce má pozici 0, což znamená, že poslední znak bude mít pozici string.length - 1. Jinými slovy, dvouznakový řetězec má délku 2 a jeho pozice znaků budou 0 a 1.

    Napište funkci countBs, která vezme řetězec jako argument a vrátí počet znaků "B" v řetězci.

    Potom napište funkci countChar, která funguje trochu jako countBs, až na to, že potřebuje druhý parametr, znak, který budeme v řetězci hledat (místo pouhého počítání počtu znaků „B“). Chcete-li to provést, přepište funkci countBs.