Existuje jeÅ¡tÄ jeden způsob, jak vytvoÅit funkci. PoužÃvá se jen zÅÃdka, ale nÄkdy nemáme jinou možnost.
Syntaxe
Syntaxe vytvoÅenà funkce:
let funkce = new Function ([arg1, arg2, ...argN], tÄloFunkce);
Funkce je vytvoÅena s argumenty arg1...argN a zadaným tÄlem tÄloFunkce.
Je snadnÄjšà tomu porozumÄt, když se podÃváme na pÅÃklad. Toto je funkce se dvÄma argumenty:
let seÄti = new Function('a', 'b', 'return a + b');
alert( seÄti(1, 2) ); // 3
A zde je funkce bez argumentů, jenom s tÄlem:
let ÅekniAhoj = new Function('alert("Ahoj")');
ÅekniAhoj(); // Ahoj
Hlavnà rozdÃl oproti ostatnÃm způsobům, jaké jsme vidÄli, je, že funkce je vytvoÅena doslovnÄ z ÅetÄzce, který je pÅedán za bÄhu skriptu.
VÅ¡echny pÅedchozà deklarace po nás programátorech požadovaly, abychom zapsali kód funkce do skriptu.
AvÅ¡ak new Function umožÅuje pÅevést libovolný ÅetÄzec na funkci. NapÅÃklad můžeme zÃskat novou funkci ze serveru a pak ji spustit:
let ÅetÄzec = ... dynamické zÃskánà kódu ze serveru ...
let funkce = new Function(ÅetÄzec);
funkce();
PoužÃvá se jen ve velmi specifických pÅÃpadech, napÅÃklad když zÃskáme kód ze serveru, nebo když chceme dynamicky kompilovat funkci ze Å¡ablony ve složitých webových aplikacÃch.
UzávÄr
Funkce si zpravidla pamatuje, kde se zrodila, ve speciálnà vlastnosti [[Environment]]. Ta se odkazuje na lexikálnà prostÅedÃ, z nÄhož byla funkce vytvoÅena (probrali jsme to v kapitole Oblast platnosti promÄnné, uzávÄr).
Když je vÅ¡ak funkce vytvoÅena pomocà new Function, jejà vlastnost [[Environment]] se nenastavà na odkaz na aktuálnà lexikálnà prostÅedÃ, ale na globálnÃ.
Taková funkce tedy nemá pÅÃstup k vnÄjÅ¡Ãm promÄnným, jedinÄ ke globálnÃm.
function vraťFunkci() {
let hodnota = "test";
let funkce = new Function('alert(hodnota)');
return funkce;
}
vraťFunkci()(); // chyba: hodnota nenà definována
Porovnejte si to s bÄžným chovánÃm:
function vraťFunkci() {
let hodnota = "test";
let funkce = function() { alert(hodnota); };
return funkce;
}
vraÅ¥Funkci()(); // "test", z lexikálnÃho prostÅedà funkce vraÅ¥Funkci
Tato speciálnà vlastnost new Function vypadá zvláštnÄ, ale v praxi se ukazuje být velmi užiteÄná.
PÅedstavme si, že musÃme vytvoÅit funkci z ÅetÄzce. Kód této funkce nenà znám v dobÄ psanà skriptu (to je důvod, proÄ nepoužijeme obvyklou funkci), ale bude znám pÅi jeho bÄhu. Můžeme jej zÃskat ze serveru nebo z jiného zdroje.
NaÅ¡e nová funkce musà interagovat s hlavnÃm skriptem.
Co kdyby mohla pÅistupovat k vnÄjÅ¡Ãm promÄnným?
Problém je v tom, že pÅedtÃm, než je JavaScriptový skript zveÅejnÄn k použÃvánÃ, je zkomprimován minifikátorem â speciálnÃm programem, který zkrátà kód tÃm, že odstranà komentáÅe, pÅebyteÄné mezery a â co je důležité, pÅejmenuje názvy lokálnÃch promÄnných na kratÅ¡Ã.
NapÅÃklad jestliže funkce obsahuje let uživatelskéJméno, minifikátor je nahradà za let a (nebo jiné pÃsmeno, které jeÅ¡tÄ nenà použito) a uÄinà tak vÅ¡ude. To je obvykle bezpeÄné, jelikož promÄnná je lokálnà a nic mimo funkci k nà nemůže pÅistupovat. A uvnitÅ funkce minifikátor nahradà tuto promÄnnou vÅ¡ude, kde je uvedena. Minifikátory jsou chytré, analyzujà strukturu kódu, takže nic nerozbÃjejÃ. Nenà to jen tupé najdi a nahraÄ.
Kdyby tedy new Function mÄla pÅÃstup k vnÄjÅ¡Ãm promÄnným, nedokázala by najÃt pÅejmenované uživatelskéJméno.
Kdyby new Function mÄla pÅÃstup k vnÄjÅ¡Ãm promÄnným, mÄla by problémy s minifikátory.
NavÃc by takový kód byl architektonicky Å¡patný a náchylný k chybám.
K tomu, abychom nÄco pÅedali funkci vytvoÅené pomocà new Function, bychom mÄli použÃvat jejà argumenty.
ShrnutÃ
Syntaxe:
let funkce = new Function ([arg1, arg2, ...argN], tÄloFunkce);
Z historických důvodů můžeme argumenty uvést i jako seznam oddÄlený Äárkou.
Tyto tÅi deklarace znamenajà totéž:
new Function('a', 'b', 'return a + b'); // základnà syntaxe
new Function('a,b', 'return a + b'); // oddÄlené Äárkou
new Function('a , b', 'return a + b'); // oddÄlené Äárkou s mezerami
Vlastnost [[Environment]] funkcà vytvoÅených pomocà new Function se odkazuje na globálnà lexikálnà prostÅedÃ, ne na vnÄjÅ¡Ã. Proto tyto funkce nemohou použÃvat vnÄjšà promÄnné. To je vÅ¡ak ve skuteÄnosti dobÅe, protože nás to ochraÅuje pÅed chybami. Výslovné pÅedávánà parametrů je architektonicky mnohem lepšà způsob a nezpůsobuje problémy s minifikátory.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)