Funkcionální programování. Použití tlačítka HTML k volání funkce JavaScriptu

  • Překlad

Často se setkávám s kódem JavaScriptu, 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á funkční programovací mechanismy. Je čas prozkoumat tyto možnosti. V tomto článku vám řeknu pět způsobů, jak volat funkce 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í volání Začátečníci často deklarují funkce, jak je uvedeno v příkladu výše. Volání této funkce je snadné:
makeArray("jeden", "dva"); // => [ okno, "jeden", "dva" ]
Počkejte. Odkud pochází objekt okna? Proč se to rovná oknu?

V JavaScriptu, bez ohledu na to, zda je skript spuštěn v prohlížeči nebo v jiném prostředí, je vždy definován globální objekt. Jakýkoli kód v našem skriptu, který není „vázán“ na nic (tj. mimo deklaraci objektu), je ve skutečnosti v kontextu globálního objektu. V našem případě není makeArray pouze funkcí, která „chodí“ 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é 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á přítomnost globální funkce. A všichni víme, že globální funkce a proměnné nejsou nejlepší formou v programování. To platí zejména pro JavaScript. Vyhněte se globálním definicím a nebudete litovat.

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

Volání metody Vytvořme jednoduchý objekt a udělejme z makeArray jeho metodu. Pojďme deklarovat objekt pomocí doslovného zápisu a pak zavolejte 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? 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 jako každý jiný objekt lze funkce předávat a kopírovat. V tomto případě jsme v podstatě 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í prohlášení, jako je toto:
var arrayMaker = ( someProperty: "Nějaká hodnota"; make: function (arg1, arg2) ( return [ this, arg1, arg2]; ) );
Pravidlo #2 volání funkce: Ve funkci volané pomocí syntaxe volání metody, jako je obj.myFunction() nebo obj["myFunction"]() , bude mít hodnotu obj .

Nepochopení tohoto obecně jednoduchého principu často vede k chybám při zpracování událostí:
function buttonClicked())( var text = (toto === okno) ? "okno" : this.id; alert(text); ) var button1 = document.getElementById("btn1"); var button2 = document.getElementById("btn2"); button1.onclick = buttonClicked; button2.onclick = function())( buttonClicked(); );
Po kliknutí 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, ke 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ž tagu elementu přiřadíme handler události, jako v případě třetího tlačítka. Kliknutím na třetí tlačítko se zobrazí stejná zpráva jako na druhé.

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ý vyvolal událost:
// 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() Je logické, že čí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 nimi jsou v následujících argumentech: Function.apply() přijímá pole hodnot, které budou předány funkci, zatímco Function.call() přijímá argumenty samostatně. V praxi je podle mého názoru pohodlnější použít apply() .

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

Konstruktory Nebudu se podrobně zabývat deklarováním vlastních typů v JavaScriptu, ale myslím, že je nutné připomenout, že v JavaScriptu nejsou žádné třídy a každý vlastní typ potřebuje konstruktor. Navíc je lepší deklarovat metody vlastního typu pomocí prototype , což je vlastnost funkce konstruktoru. Vytvořme si vlastní typ:
// deklarujte funkci konstruktoru ArrayMaker(arg1, arg2) ( this.someProperty = "nezáleží"; this.theArray = [ this, arg1, arg2 ]; ) // deklarujte metody ArrayMaker.prototype = ( someMethod: function () ( alert( "Voláno nějakou metodou" getArray: function () ( return this.theArray; ) ); var am = new ArrayMaker("jeden", "dva"); var other = new ArrayMaker("první", "druhý"); am.getArray(); // => [ am, "jeden", "dva" ]
Důležitá věc v tomto příkladu je přítomnost operátoru new před voláním funkce. Pokud by tomu tak nebylo, šlo by o globální volání a vlastnosti vytvořené v konstruktoru by patřily globálnímu objektu. To nepotřebujeme. Kromě toho konstruktory obvykle nevracejí hodnoty explicitně. Bez operátoru new by konstruktor vrátil nedefinováno, s ním vrátí toto. Za dobrý styl se považuje pojmenovávat konstruktory velkým písmenem; To vám připomene potřebu nového operátora.

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

Volání funkce Pravidlo č. 4: Při volání funkce s operátorem new bude jeho hodnotou nový objekt vytvořený běhovým prostředím JavaScriptu. Pokud tato funkce nevrátí žádný objekt explicitně, 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 je obtížné zachytit chyby související s touto hodnotou, takže má smysl jim předem předcházet.

Funkce

Funkce je blok kódu JavaScript, který je definován jednou a lze jej spustit nebo zavolat vícekrát. Možná již znáte koncept funkce pod jiným názvem, jako je například podprogram nebo procedura. Funkce mohou mít parametry: Definice funkce může obsahovat seznam identifikátorů, které se nazývají parametry a fungují jako lokální proměnné v těle funkce.

Při volání funkcí jim mohou být předány hodnoty nebo argumenty odpovídající jejich parametrům. Funkce často používají své argumenty k výpočtu návratové hodnoty, což je hodnota výrazu volání funkce. Kromě argumentů je při volání jakékoli funkce předána ještě jedna hodnota, která definuje kontext volání – hodnota v klíčovém slově this.

Funkce v JavaScriptu jsou objekty a lze je používat různými způsoby. Například funkce mohou být přiřazeny proměnným a předány jiným funkcím. Protože funkce jsou objekty, můžete jejich vlastnostem přiřadit hodnoty a dokonce volat jejich metody.

JavaScript umožňuje vnoření definic funkcí do jiných funkcí a takové funkce budou mít přístup ke všem proměnným přítomným v rozsahu definice.

Definování funkcí

Definice funkce začíná klíčovým slovem function, za kterým následují následující komponenty:

Identifikátor, který určuje název funkce

Název je povinnou součástí příkazu deklarace funkce: bude použit k vytvoření nové proměnné, ke které bude přiřazen nový funkční objekt. Ve výrazech definice funkce může název chybět: pokud je přítomen, bude název odkazovat na objekt funkce pouze v těle samotné funkce.

Dvojice závorek kolem seznamu nula nebo více identifikátorů oddělených čárkami

Tyto identifikátory budou definovat názvy parametrů funkce a lze je použít jako lokální proměnné v těle funkce.

Dvojice složených závorek s žádnými nebo více pokyny pro JavaScript uvnitř

Tyto instrukce tvoří tělo funkce: provádějí se pokaždé, když je funkce volána.

Následující příklad ukazuje několik definic funkcí ve formě příkazů a výrazů. Všimněte si, že definice funkcí jako výrazy jsou užitečné pouze v případě, že jsou součástí větších výrazů, jako je přiřazení nebo volání funkce, které něco dělají s nově deklarovanou funkcí:

// Vypíše názvy a hodnoty všech vlastností objektu obj funkce printprops(obj) ( for(var p v obj) console.log(p + ": " + obj[p] + "\n"); ) // Vypočítá vzdálenost mezi body (x1,y1) a (x2,y2) funkce distance(x1, y1, x2, y2) ( var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt(dx *dx + dy*dy ) // Rekurzivní funkce (volá sama sebe), která vypočítá faktoriál faktorial(x) ( if (x)

Všimněte si, že ve výrazech definice funkce nemusí být název funkce přítomen. Příkaz deklarace funkce ve skutečnosti deklaruje proměnnou a přiřadí jí funkční objekt.

Na druhé straně výraz definice funkce nedeklaruje proměnnou. V definičních výrazech je však možné zadat název funkce, jako ve výše uvedené faktoriálové funkci, což může být vyžadováno v těle funkce, aby se sama zavolala. Pokud výraz definice funkce obsahuje název, bude tento název odkazovat na funkční objekt v rozsahu dané funkce. Ve skutečnosti se název funkce stane lokální proměnnou, která je přístupná pouze v těle funkce. Ve většině případů nemusí být název funkce uveden v definičních výrazech, takže definice jsou kompaktnější.

Všimněte si, že většina (ale ne všechny) funkcí v příkladu obsahuje příkaz return. Příkaz return ukončí funkci a vrátí hodnotu jejího výrazu (pokud je zadán) volajícímu programu. Pokud v příkazu return není žádný výraz, vrátí nedefinovaný. Pokud ve funkci není žádný příkaz return, interpret jednoduše provede všechny příkazy v těle funkce a vrátí volajícímu programu nedefinovaný.

Většina funkcí v příkladu se vyhodnotí na nějakou hodnotu a pomocí příkazu return vrátí tuto hodnotu volajícímu programu. Funkce printprops() je v tomto smyslu mírně odlišná: jejím úkolem je tisknout názvy vlastností objektu. Nemusí vracet žádnou hodnotu, takže ve funkci není žádný příkaz return. Funkce printprops() vždy vrátí hodnotu nedefinovaná. (Funkce, které nemají návratovou hodnotu, se někdy nazývají procedury.)

Volání funkcí

Programový kód, který tvoří tělo funkce, se nespustí v okamžiku, kdy je funkce definována, ale v okamžiku, kdy je volána. Volání funkcí se provádí pomocí výrazu volání. Volací výraz se skládá z výrazu volání funkce, který vrací objekt funkce následovaný závorkami se seznamem nulových nebo více argumentů oddělených čárkami uvnitř.

Pokud je výraz volání funkce výraz volání vlastnosti – pokud je funkce vlastností objektu nebo prvku pole (tj. metoda) – pak výraz volání je výraz volání metody. Následující úryvek ukazuje několik příkladů běžných výrazů volání funkcí:

Printprops((x:4, věk: 24)); var d = vzdálenost(1,1,5,6); var f = faktoriál(5) / faktoriál(12); f = čtverec(5);

Při volání funkce se vyhodnotí všechny výrazy argumentů (uvedené v závorkách) a výsledné hodnoty se použijí jako argumenty funkce. Tyto hodnoty jsou přiřazeny parametrům, jejichž názvy jsou uvedeny v definici funkce. V těle funkce vrátí výrazy volání parametrů hodnoty odpovídajících argumentů.

Když je volána normální funkce, návratová hodnota funkce se stane hodnotou volajícího výrazu. Pokud se funkce vrátí poté, co interpret dosáhl svého konce, vrátí se undefined. Pokud se funkce vrátí jako výsledek příkazu return, je vrácena hodnota výrazu následujícího po příkazu return nebo nedefinovaná, pokud příkaz return neobsahuje žádný výraz.

Metoda není nic jiného než funkce, která je uložena jako vlastnost objektu. Pokud máte funkci func a objekt obj, můžete definovat metodu na obj s názvem metoda, jak je uvedeno níže:

// Definice jednoduchého objektu a funkce var obj = (); function func(a, b) ( return a+b;) // Přidání metody do objektu obj obj.method = func; // Nyní můžete tuto metodu zavolat var result = obj.method(4, 5);

Nejčastěji se při volání metod používá forma přístupu k vlastnosti pomocí operátoru tečka, ale lze použít i formu přístupu k vlastnosti pomocí hranatých závorek. Například oba následující výrazy jsou výrazy volání metody:

Vysledek = obj.method(4, 5); vysledek = obj["metoda"](4, 5);

Argumenty a návratová hodnota volání metody jsou zpracovány stejným způsobem jako normální volání funkce. Volání metody má však jeden důležitý rozdíl: kontext volání. Výraz pro přístup k vlastnosti se skládá ze dvou částí: objektu (v tomto případě obj) a názvu vlastnosti (metody). V takových výrazech volání metody se obj stává volajícím kontextem a tělo funkce je schopno odkazovat na tento objekt pomocí klíčového slova this. Například:

Var obj = ( x: 0, y: 0, // Přidat metodu: funkce(a, b) ( this.x = a; this.y = b; ), // Další součet metody: funkce() ( vrátit toto .x + this.y )); // Volání metod obj.add(15, 4); console.log(obj.sum()); // 19

Metody a klíčové slovo this jsou stěžejní pro paradigma objektově orientovaného programování. Jakákoli funkce použitá jako metoda ve skutečnosti přijímá implicitní argument - objekt, na kterém byla volána. Metody obvykle provádějí nějakou operaci s objektem a syntaxe volání metody jasně odráží skutečnost, že funkce pracuje s objektem.

Poznámka: toto je klíčové slovo, nikoli název proměnné nebo vlastnosti. Syntaxe JavaScriptu neumožňuje elementu this přiřadit hodnotu.

Funkční argumenty a parametry

V JavaScriptu definice funkcí neurčují typy parametrů a volání funkcí neprovádějí žádnou kontrolu typu předávaných hodnot argumentů. JavaScript ve skutečnosti ani nekontroluje počet argumentů při volání funkcí. Níže uvedené pododdíly popisují, co se stane, pokud je počet argumentů ve volání funkce menší nebo větší než počet deklarovaných parametrů. Ukazují také, jak můžete explicitně zkontrolovat typy argumentů funkce, pokud potřebujete zajistit, aby funkce nebyla volána s neplatnými argumenty.

Nepovinné argumenty

Když je počet argumentů ve volání funkce menší než počet deklarovaných parametrů, jsou chybějící argumenty nastaveny na nedefinováno. Často je vhodné psát funkce tak, že některé argumenty jsou nepovinné a lze je při volání funkce vynechat. V tomto případě je žádoucí poskytnout možnost přiřadit přiměřeně rozumné výchozí hodnoty parametrům, které mohou být vynechány. Například:

// Přidejte vyčíslitelná jména // vlastností objektu obj do pole arr a vraťte jej. Pokud argument // arr nebyl předán, vytvořte a vraťte novou funkci pole getPropertyNames(obj, /* volitelné */ arr) ( if (arr === nedefinováno) arr = ; // Pokud pole není definováno, vytvořte a new for( vlastnost var v obj) arr.push(property return arr // Tuto funkci lze volat s 1 nebo 2 argumenty: var a = getPropertyNames((x:1, y:1)); // Získání vlastností objektu v novém poli getPropertyNames((z:5),a); // přidá vlastnosti nového objektu do tohoto pole console.log(a); // ["x", "y", "z"]

Všimněte si, že při deklaraci funkcí musí volitelné argumenty doplnit seznam argumentů, aby byly vynechány. Programátor, který bude psát volání vaší funkce, nebude moci předat druhý argument a zároveň vynechat první: bude nucen explicitně předat hodnotu nedefinovanou v prvním argumentu. Všimněte si také komentáře /* optional */ v definici funkce, který zdůrazňuje skutečnost, že parametr je volitelný.

Seznamy argumentů s proměnnou délkou

Pokud počet argumentů ve volání funkce překročí počet názvů parametrů, funkce nebude moci přímo přistupovat k nepojmenovaným hodnotám. Řešení tohoto problému poskytuje objekt Arguments. V těle funkce odkazuje identifikátor argumentů na objekt Arguments přítomný ve volání. Objekt Arguments je objekt podobný poli, který umožňuje, aby hodnoty předané funkci byly načteny podle jejich čísel, nikoli podle jejich jmen.

Předpokládejme, že byla definována funkce func, která vyžaduje jeden argument x. Pokud tuto funkci zavoláte se dvěma argumenty, první bude dostupný uvnitř funkce pod názvem parametru x nebo jako argumenty. Druhý argument bude dostupný pouze jako argumenty. Navíc, stejně jako skutečná pole, mají argumenty vlastnost length, která určuje počet prvků, které obsahuje. To znamená, že v těle funkce zvané func se dvěma argumenty má arguments.length hodnotu 2.

Objekt Arguments lze použít pro různé účely. Následující příklad ukazuje, jak jej použít ke kontrole, zda byla funkce volána se správným počtem argumentů, což JavaScript za vás neudělá:

Funkce func(x, y, z) ( // Nejprve zkontroluje, zda je předán správný počet argumentů if (arguments.length != 3) ( vyvolá novou chybu Error("Func volána s argumenty " + arguments.length + " a požadované 3."); ) // A nyní samotný kód funkce... )

Všimněte si, že často není nutné kontrolovat počet argumentů, jako v tomto příkladu. Výchozí chování interpretu JavaScriptu je ve většině případů v pořádku: chybějící argumenty jsou nahrazeny hodnotou undefined a další argumenty jsou jednoduše ignorovány.

Objekt Arguments ilustruje důležitou vlastnost funkcí JavaScriptu: mohou být zapsány tak, aby přebíraly libovolný počet argumentů. Následující funkce přebírá libovolný počet argumentů a vrací hodnotu největšího z nich (vestavěná funkce Math.max() se chová podobně):

Funkce maxNumber() ( var m = Číslo.NEGATIVE_INFINITY; // Procházet všechny argumenty, najít a // uložit největší z nich pro (var i = 0; i m) m = argumenty[i]; // Vrácení největší hodnoty m ; ) var největší = maxNumber(1, 10, 100, 2, 3, 1000, 4, 5, 10000, 6); // 10 000

Funkce, jako je tato, které mohou mít libovolný počet argumentů, se nazývají variadické funkce, funkce proměnné arity nebo funkce varargs. Tento termín vznikl s příchodem programovacího jazyka C.

Všimněte si, že nesmí být povoleno volání variadic funkcí s prázdným seznamem argumentů. Při psaní funkce, která očekává pevný počet požadovaných pojmenovaných argumentů, za nimiž následuje libovolný počet volitelných nepojmenovaných argumentů, dává naprosto smysl používat objekt arguments.

Nezapomeňte, že argumenty ve skutečnosti nejsou pole – je to objekt Argumenty. Každý objekt Arguments má očíslované prvky pole a vlastnost length, ale technicky se nejedná o pole. Je lepší si to představit jako objekt, který má nějaké očíslované vlastnosti.

Kromě prvků pole definuje objekt Arguments vlastnosti volaného a volajícího. Pokus o změnu hodnot těchto vlastností v přísném režimu ECMAScript 5 zaručeně vyvolá výjimku TypeError. V laxním režimu však standard ECMAScript uvádí, že vlastnost volaného odkazuje na aktuálně prováděnou funkci. Vlastnost caller není standardní, ale je přítomna v mnoha implementacích a odkazuje na funkci, která volala aktuální.

Vlastnost caller může být použita pro přístup k zásobníku volání a vlastnost callee je zvláště užitečná pro rekurzivní volání nepojmenovaných funkcí:

Proměnný faktoriál = funkce (x) ( if (x

Vlastnosti a metody funkce

Viděli jsme, že funkce mohou být použity jako hodnoty v programech JavaScript. Operátor typeof vrací pro funkce řetězec "funkce", ale funkce jsou ve skutečnosti speciálním druhem objektů v JavaScriptu. A protože funkce jsou objekty, mají vlastnosti a metody jako jakékoli jiné objekty. Existuje dokonce konstruktor Function(), který vytváří nové funkční objekty. Následující podkapitoly popisují vlastnosti a metody funkcí.

vlastnost délky

Vlastnost arguments.length v těle funkce určuje počet argumentů předávaných funkci. Vlastní délka funkce má však jiný význam. Tato vlastnost pouze pro čtení vrací počet argumentů, které funkce očekává, že obdrží – počet deklarovaných parametrů.

Následující úryvek definuje funkci nazvanou check(), která přijímá pole argumentů z jiné funkce. Porovná vlastnost arguments.length (počet skutečně předaných argumentů) s vlastností arguments.callee.length (počet očekávaných argumentů), aby určil, zda bylo funkci předáno tolik argumentů, kolik očekává. Pokud se hodnoty neshodují, je vyvolána výjimka. Po funkci check() následuje testovací funkce func(), která ukazuje, jak používat funkci check():

// Tato funkce používá arguments.callee, takže // nebude fungovat v přísném režimu funkce check(args) ( var Actual = args.length; // Skutečný počet argumentů var expect = args.callee.length; // Očekávané počet argumentů if (skutečné !== očekávané) // Pokud se neshodují, je vyvolána výjimka throw new Error("expected: " + očekávané + "; přijato " + skutečné ) funkce func(x, y, z) ( // Kontrola počtu očekávaných a skutečně prodaných argumentů check(arguments // Nyní proveďte zbytek funkce return x + y + z);

vlastnost prototypu

Každá funkce má vlastnost prototypu, která odkazuje na objekt známý jako objekt prototypu. Každá funkce má svůj vlastní prototypový objekt. Když je funkce použita jako konstruktor, nově vytvořený objekt zdědí vlastnosti tohoto prototypového objektu.

Prototypy a vlastnosti prototypu byly probrány v předchozím článku.

metody call() a apply().

Metody call() a apply() umožňují volat funkci nepřímo, jako by to byla metoda na nějakém jiném objektu. První argument pro metody call() a apply() je objekt, na kterém je funkce volána; tento argument určuje kontext volání a stává se hodnotou klíčového slova this v těle funkce. Chcete-li volat funkci func() (bez argumentů) jako metodu obj, můžete použít kteroukoli z metod call() nebo apply():

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

Oba způsoby jeho volání jsou ekvivalentní následujícímu fragmentu (za předpokladu, že obj nemá vlastnost s názvem m):

Obj.m = func; // Dočasně udělá z func metodu obj obj.m(); // Zavolejte to bez argumentů. deleteobj.m; // Odstraňte dočasnou metodu.

V přísném režimu ECMAScript 5 se první argument metod call() a apply() stává hodnotou této, i když je to jednoduchá hodnota, null nebo nedefinovaná. V ECMAScript 3 a v laxním režimu jsou hodnoty null a undefined nahrazeny globálním objektem a jednoduchá hodnota je nahrazena odpovídajícím obalem.

Všechny ostatní argumenty metody call() následující po prvním argumentu určujícím kontext volání jsou předány volané funkci. Metoda apply() se chová jako metoda call() kromě toho, že argumenty funkce jsou předány jako pole. Pokud je funkce schopna zpracovat libovolný počet argumentů, lze k volání takové funkce použít metodu apply() v kontextu pole libovolné délky.

Následující příklad ukazuje praktické použití metody call():

// Níže jsou uvedeny dvě funkce, které zobrazují vlastnosti a // hodnoty vlastností libovolného objektu. Metoda // displeje jsou předány jako argument funkce func print1(func, obj) ( for (n v obj) func(n +": " + obj[n]); ) funkce print2(func, objDevice, obj) ( for ( n v obj) func.call(objDevice, n +": " + obj[n] ) var obj = (x:5, y:10); print2(dokument.zapis, dokument, obj); // Funguje správně print2(console.log, console, obj); tisk1(dokument.zápis, obj); // Dojde k výjimce neplatného vyvolání, protože print1(console.log, obj); // není možné volat tyto metody bez kontextového objektu

metoda bind().

Metoda bind() se poprvé objevila v ECMAScriptu 5, ale lze ji snadno napodobit v ECMAScriptu 3. Jak její název napovídá, hlavním účelem metody bind() je svázat funkci s objektem. Pokud zavoláte metodu bind() funkce func a předáte jí objekt obj, vrátí novou funkci. Volání nové funkce (jako běžné funkce) zavolá původní funkci func jako metodu na obj. Všechny argumenty předané nové funkci budou předány původní funkci. Například:

// Funkce, kterou chcete svázat funkci func(y) ( return this.x + y; ) var obj = (x:1); // Objekt pro vazbu na var g = func.bind(obj); // Volání g(x) zavolá obj.func(x)

Tento typ vazby lze snadno implementovat v ECMAScript 3, jak je znázorněno níže:

// Vrátí funkci, která volá funkci func jako metodu objektu obj // a předá jí všechny své argumenty function bind(func, obj) ( if (func.bind) return func.bind(obj); // Use bind method if dostupné else return function() ( // Jinak svázat jako níže return func.apply(obj, arguments); )

Metoda bind() v ECMAScript 5 dělá více než jen váže funkci k objektu. Provádí také částečné přetypování: kromě hodnoty this budou svázány všechny argumenty předané metodě bind() po jejím prvním argumentu. Částečná aplikace je běžná technika ve funkcionálním programování a někdy se jí říká kari.

Myšlenky dynamického generování obsahu na webovém zdroji se staly normou. Statické stránky a vytváření šablon webových stránek konečně dokončily své poslání.

Moderní webový zdroj však nemusí být nutně představován sadou stránek generovaných serverem a aktualizovaných prohlížečem (JS+AJAX).

Když přijde návštěvník, webový zdroj se může skládat z několika hlaviček pro protokol, nějakého textu v „hlavě“, několika řádků kódu v „těle“ a je to. Zbytek " přijde s nápadem” během návštěvnické zkušenosti - toto je ideální místo nebo aspirující na to být.

Místo popisu a podstata funkcí

JavaScript je zkušenost získaná po mnoho desetiletí. Má významnou vývojovou historii a moderní, kvalifikovaný tým tvůrců a vývojářů. Jazyk je dobře promyšlený, spolehlivý, krásný a poskytuje vývojářům skutečnou příležitost psát slušný kód a zlepšovat se.

Koncept algoritmu mimo funkci zde v zásadě chybí. Vývojář samozřejmě může vložit skript kamkoli na stránku, umístit do něj kód a ten se spustí. Jaký je však smysl kódu, který se provede pouze jednou: když se stránka načte (znovu načte)? Pokud není možné nastavit počáteční hodnoty některých nedůležitých proměnných.

Skript je místo pro popis nezbytných proměnných a funkcí, spíše než dobrý kus kódu napsaný sám pro sebe. Podstatný a podstatný je právě soubor funkcí, možná jejich vzájemná přímá souvislost, ale častěji je vše jinak. Místo, kde je funkce popsána, a místo, kde je aplikována, nejsou vůbec totéž.

Není vůbec nutné, aby funkce volala jinou funkci přímo, může to dělat nepřímo prostřednictvím dynamického generování kódu. Návštěvník se v rámci tohoto kódu rozhodne a spustí se zcela jiný systém funkcí.

Funkční dynamika

Funkční dynamika nejsou pouze a ne tak obslužné rutiny přiřazené prvkům stránky, jsou to funkce, které tvoří prvky stránky, a přímé ovladače se mohou také měnit.

Akce na stránce se odvíjí v závislosti na jejích prvcích a chování návštěvníka na ní. Pohyby myši, tlačítka klávesnice, kliknutí, události prvků a další okolnosti vedou ke spuštění potřebných funkcí.

Zpočátku neexistuje žádná sekvence a není zde žádný paralelismus. Webový zdroj má adekvátní odezvu na události. Jak rychle bude JavaScript vykonávat určitou funkci, závisí na mnoha technických (počítač, komunikační linky) a sémantických (logika algoritmu, předmět, význam úlohy) faktorech.

Ve skutečnosti lze říci, že něco fungovalo paralelně a něco se splní po něčem, ale v tom není žádný zvláštní význam. Je důležité, aby funkce JavaScriptu umožňovaly vytvářet adekvátní odezvu na akce návštěvníků.

Toto je nové myšlení ve vývoji: distribuované zpracování informací v útrobách jediného prohlížeče!

Syntaxe proměnných a funkcí

Proměnné JavaScriptu jsou umístěny jak ve značce „script“, tak v těle funkce. Funkce jsou definovány stejným způsobem. Není žádný zvláštní smysl psát do funkce další funkci, ale to může být nutné z různých a dobře podložených důvodů.

Popis funkce obvykle začíná klíčovým slovem "function", za kterým následuje její název, seznam argumentů v závorkách oddělených čárkami a tělo funkce ve složených závorkách.

Tento příklad popisuje dvě funkce, které zajišťují výměnu AJAX mezi stránkou a serverem. Proměnná scXHR je popsána výše, proto je dostupná v InitXML i uvnitř WaitReplySC.

Název funkce a parametr "funkce".

Byla zde zavedena asynchronní možnost, kdy se funkce JavaScriptu ve funkci zavolá poté, co server odpoví. Současně po obdržení odpovědi ze serveru WaitReplySC přistupuje ke značkám stránky, naplňuje je přijatými informacemi a volá další funkce, které mohou iniciovat další požadavek na server.

Zde je také důležité poznamenat, že WaitReplySC je funkce. Ale v řadě scXHR.onreadystatechange = WaitReplySC je předán jako parametr. Toto je obecné pravidlo pro předávání funkcí jiným funkcím jako parametrů. Určete hranaté závorky a předejte do nich její parametry - funkce se provede okamžitě. Dal mi jen své jméno, ale tak co. Volání funkce provede ten, kdo obdržel její jméno.

Funkčnost implementovaná prostřednictvím AJAX vám umožňuje volat funkci JavaScript prostřednictvím dat přijatých ze serveru. Ve skutečnosti při odesílání požadavku na server určitá funkce nemusí vůbec „vědět“, ke které funkci přistupuje a s jakými informacemi.

Ukončení funkce a jeho výsledek

V těle funkce můžete napsat libovolné operátory jazyka, který je ve skutečnosti k tomuto účelu určen. Proměnné definované uvnitř a vně funkce jsou dostupné v rámci funkce, ale ne ty, které jsou definovány v jiných funkcích.

Pokud chcete, aby funkce vrátila výsledek, můžete použít příkaz return v JavaScriptu: return. V těle funkce může být dostatečný počet příkazů return. Není vůbec nutné, aby všechny vracely stejný typ výsledku.

Vývojáři obvykle tuto funkci velmi respektují a v závislosti na situaci se rozhodnou funkci co nejdříve ukončit.

Není vůbec nutné procházet celý funkční algoritmus, když můžete skončit dříve.

Funkční argumenty

Argumenty funkce jsou předávány jako seznam oddělený čárkami, uzavřený v závorkách a umístěný bezprostředně za jejím názvem. Názvy proměnných se používají jako argumenty, ale hodnoty lze také předávat přímo. Chcete-li předat funkci funkci v JavaScriptu, stačí zadat její název bez závorek.

Uvnitř funkce je k dispozici proměnná arguments, která má vlastnost length. K libovolnému argumentu funkce můžete přistupovat prostřednictvím argumentů, argumentů,... až po poslední argumenty.

Změna argumentu funkce je platná uvnitř funkce, ale ne mimo ni. Abyste mohli něco změnit mimo funkci, musíte použít JavaScriptový návratový operátor, přes který předáte požadovanou hodnotu ven.

Po dokončení funkce bude vše spojené s jejím provedením zničeno. Během provádění může funkce měnit vnější proměnné, kromě těch, které jsou popsány v jiných funkcích, včetně interních.

arguments má vlastnost volaného, ​​která je určena k volání funkce, která se v daném čase provádí. Pokud zavoláte sama sebe, JavaScriptová verze funkce v rámci funkce vám umožní implementovat rekurzi.

Používání funkcí

Hlavním úkolem funkcí je obsluhovat události prohlížeče. K tomu je téměř v každém tagu možné zadat název události a funkci, která ji zpracovává. Lze zadat více událostí, ale pro každou událost je určena pouze jedna funkce.

Jedna funkce může obsluhovat více prvků stránky a více událostí. Pomocí parametru „this“ můžete předat informace funkci, odkud byla volána.

Klasickým využitím funkcí JS jsou obslužné rutiny událostí na prvcích. V tomto příkladu bude funkce scfWecomeGo() nebo scfWelcomeCancel() volána ve formuláři pro přihlášení/odhlášení návštěvníka a scfMenuItemClick(this) při výběru provozního režimu.

V druhém případě je předán parametr „toto“, který vám umožní zázračně zjistit, ze kterého divu volání přišlo. Obecně platí, že JavaScript je tak dobře implantován do DOM a umožňuje vám procházet jeho prvky tak pohodlně a sbírat potřebné informace, že dynamika stránky může být jednoduše nepředvídatelná.

Funkce nemusí vracet řetězec znaků, číslo nebo jinou funkci. Dokáže vrátit plnohodnotný HTML element, který bude obsahovat požadovaný počet elementů, s vlastními obslužnými rutinami událostí.

Umístěním takového prvku na stránku vytváří vývojář novou funkcionalitu, která je dobrá z hlediska řešení problému a uspokojování zájmů návštěvníků, ale poměrně náročná z hlediska implementace.

Při spuštění takového plnohodnotného vývoje je snadné se zmást ve vlastním kódu, ve volání funkcí, ve chvílích, kdy se tvoří ten či onen obsah té či oné části stránky. Než se vydáte tímto směrem vývoje, neuškodí vše pečlivě zvážit.

O distribuovaném myšlení

Vývojář musí myslet na úrovni všech prvků stránky, na úrovni všech událostí a mít jasnou představu o tom, jak se vlastně všechno děje. Je to náročné, ale ta práce za to stojí.

V JavaScriptu může být provedení funkce odloženo, dokud nenastane nějaká událost, a takových funkcí může být mnoho a události mají tendenci se šířit a spadat do „sféry viditelnosti“ různých ovladačů.

V tomto příkladu byla někde dříve volána funkce, která iniciovala vytvoření položky nabídky navigace v souboru. Předpokládá se organizace stránky, to znamená, že v okně je pouze sedm souborů, které lze odstranit a zpracovat. Můžete se pohybovat buď kliknutím na řádek souboru, pomocí šipek na klávesnici, nebo v blocích po sedmi řádcích.

Každý případ má své vlastní funkce. Jinými slovy, v takovém jednoduchém příkladu je potřeba napsat pár desítek funkcí, které budou reagovat na různé události a některé z těchto funkcí zpracují různé možnosti a situace, které s událostmi vůbec nesouvisí.

Když například odstraníte řádek, spodní by se měly posunout nahoru. K tomu budete muset buď udělat nový výběr, který je triviální a náročný na zdroje, nebo přepočítat řádky, použít funkce pole v javascriptu a elegantně dosáhnout cíle.

Funkce Argumenty a výsledky

JavaScript vám umožňuje uvést váš kód do „plně funkčního“ stavu. Je normální, že argument funkce je funkcí. Volba je povolena, když funkce vrací funkci. JavaScript je v tomto zcela uvolněný.

Je to dobrý mechanismus, ale poměrně složitý z hlediska implementace. Technicky je přípustné vše, pouze kvalifikovaný vývojář může sémanticky poskytnout logiku pro přenos „funkčnosti“.

Když je v JavaScriptu funkce uvnitř funkce, všechno jde dobře, ale když funkce generuje funkci a ta generuje jinou, pak je docela obtížné dodržovat logiku. V podstatě nejde o uplatnění kvalifikace, ale o získání bezpečného a správného výsledku.

Zájem vývojáře je jasný a jednoduchý. Vyskytl se problém, potřebujete řešení, nikoli chybu typu „Chyba JavaScriptu, operace není bezpečná“, prázdná obrazovka nebo zastavení celého enginu prohlížeče.

Pokud je argumentem funkce, pak vývojář předává proměnnou se speciálními vlastnostmi, to znamená, že to není číslo, ani řetězec, ani objekt. Ale použití takového argumentu může vést ke změně externích proměnných a výsledku funkce, která se provádí. V závislosti na tom, co je přenášeno, budou provedeny adekvátní změny.

Spuštění vygenerovaného kódu

Spuštění kódu generovaného během provozu jiného kódu můžete implementovat pomocí „eval“. To se nepovažuje za skvělé řešení, ale často nemůžete kód komplikovat zbytečnými funkcemi, ale omezit se na banální tvorbu řádku kódu JavaScript a jednoduše jej spustit.

V tomto příkladu je vygenerován řádek pro vložení některých informací do aktuálního div. Číslo div a obsah informací se pro různé pozice liší, takže takové řešení v této situaci nezaručuje, že poskytne situaci „chyba javascriptu, operace není bezpečná“, ale spolehlivě poskytne požadovaný efekt.

Nuance paradigmatu JavaScript „funkce ve funkci“.

Pokud existuje příležitost obejít se bez ozdůbek, je lepší ji využít. Všechny uvedené možnosti jsou dobré. V mnoha případech je to samozřejmě jediné řešení.

Klasický příklad rekurze: výpočet faktoriálu. Je docela obtížné napsat algoritmus, který jde do smyčky, ale je velmi snadné jít za hranice hodnoty. Faktorial roste příliš rychle.

Normou je však jak rekurze, tak funkce volající jinou funkci, která může provést platné zpětné volání.

Například běžný stůl. V tabulce mohou být další tabulky. Hnízdění nelze omezit. Psát vlastní sadu funkcí pro každý stůl je příliš velký luxus.

Takových příkladů lze uvést mnoho a všechny to budou skutečné a naléhavé úkoly, vůbec ne z oblasti programování. Problém proto spočívá právě v tom, že se bez kudrlinek neobejde vytvořený systém funkcí, respektive jeho odladění a následné spolehlivé fungování, se stává starostí nikoli JavaScriptu, ale vývojáře.

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 dolarem.

Za názvem funkce jsou parametry uvedeny v závorkách. I když funkce nemá žádné parametry, obsahuje pouze prázdné závorky. Poté ve složených závorkách přichází tělo funkce, které obsahuje sadu instrukcí.

Pojďme definovat nejjednodušší funkci:

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

Tato funkce se nazývá display(). Neakceptuje žá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ě jí musíte zavolat:

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

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

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

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

Můžeme také dynamicky přiřadit funkce 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žme předává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řebírá několik 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); ) suma(1, 2, 3); nech čísla = ; součet(...čísla);

Ve druhém případě jsou funkci předána čísla z pole nums. Ale aby se přenášelo nejen pole jako jedna hodnota, ale čí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. Při volání funkce však není nutné předávat hodnoty těchto parametrů. Pro kontrolu přítomnosti hodnoty parametru se používá porovnání s nedefinovanou hodnotou.

Existuje další způsob, jak definovat výchozí hodnoty parametrů:

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

Pokud parametry x a y nejsou předány žádné hodnoty, získají se jako hodnoty čísel 5 a 10. Tato metoda je stručnější a intuitivnější než srovnávání s nedefinovanou.

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 display(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


Horní