Rekurzivní proměnné v JavaScriptu
Následující příspěvek v sobě v podstatě nenese nic důležitého, ale určitě zajímavého. Většina kódu je platformě závislých buď na webovém prohlížeči, na ostatních platformách je to obvykle podobné.
JavaScript je jazyk, kde v proměnné krom hodnoty nemusí být nic, případně tam může být všechno.
Např. kód:
var a = null;
Vytvoří proměnnou a, ve které nic není. Kód:
var b = "hello world";
Vytvoří proměnnou, ve které je stringová hodnota. Jak, ale do proměnné uložit vše? No docela jednoduše do proměnné můžete uložit obsah jiné proměnné. Např:
var c = b; // Uloží do proměnné c hodnotu z proměnné b.
No a tak stejně můžeme do proměnné uložit tzv. globální proměnnou. V prohlížeči je to prostě window, v node.js je to global.
var d = window;
Tato proměnná má tu vlastnost, že pokud je v ni „vše“, tak je tam určitě i proměnná d. Tedy následující výraz jednoznačně vrátí „vše“.
d.d
Pokud tento výraz vrací „vše“, tak je tam určitě i proměnná d. Následující výraz tedy vrací „vše“.
d.d.d
… o 10 d později …
d.d.d.d.d.d.d.d.d.d.d.d.d
předchozí výraz taktéž vrátí „vše“. Jestliže vrátil „vše“, tak tam určitě je proměnná b. Následující výraz tedy vrátí stringovou hodnotu „hello world“
d.d.d.d.d.d.d.d.d.d.d.d.d.b
Tohoto efektu lze ve skutečnosti docílit i bez globální proměnné.
var pole = [];
pole.push("Hi misaz");
pole.push(pole);
var vystup = pole[1][1][1][1][1][1][1][1][1][1][0];
Po provedení se v proměnné vystup objeví hodnota „Hi misaz“. Existuje však ještě jeden příklad, který využívá faktu, že každý objekt má konstruktor, včetně konstruktoru (funkce). Vytvořme si objekt
var e = {
jmeno: "Hana"
}
Výraz:
e.constructor
vrátí konstruktor daného objektu, takže Object. Vrácená hodnota (funkce Object) má také konstruktor
e.constructor.constructor
vrátí Function, protože Object je funkce. A Funkce mají taky konstruktor, je jim funkce a tato funkce má také konstruktor….
e.constructor.constructor.constructor.constructor.constructor.constructor.constructor
vrátí Function.
Obdobný příklad je s funkcí, která vrátí sama sebe.
function f() {
return f;
}
Pak výraz:
f()()()()()()()()();
Vrátí funkci f.
Rekurzi lze samozřejmě udělat i nepřímo. Např. že do každého objektu stringu (přes prototype) vložíme do nějaké vlastnosti hodnotu typu Number a typ Number rozšíříme o vlastnost s Stringovou hodnotu, pak je můžeme za sebou do nekonečna volat.
String.prototype.foo = 5;
Number.prototype.bar = "a";
"Hi misaz".foo.bar.foo.bar.foo.bar.foo.bar.foo
Možná by se takových příkladů dalo najít víc. Některých lze docílit i v jiných jazycích, v JavaScriptu je to však obzvlášť jednoduché.