JavaScriptové perličky VI.
Malý kvíz: Co vypíše následující skript na posledním řádku?
x = new Object(); x.vlastnost = 0; y = x; x.vlastnost = 10; document.write(y.vlastnost);
Správná odpověď je "10". Přiřazení na třetím řádku totiž neznamená
zkopírování objektů, ale jen přiřazení reference na objekt. Nejlepší je si
objekty v JavaScriptu představovat jako ukazatele na objekty třeba v C++ – z
tohoto pohledu pak třetí řádek říká, že x a y ukazují
na tentýž objekt. Když pak změníme hodnotu vlastnosti vlastnost u
jednoho, musí se změnit i u druhého.
Chování operátoru přiřazení je ve většině případů rozumné, ale občas
potřebujeme objekt doopravdy zkopírovat. JavaScript samotný to neumí (nebo o tom
aspoň nevím), takže si tuto funkci budeme muset zařídit sami. Přidáme proto do
prototypu třídy Object metodu clone, která jako svou
návratovou hodnotu vydá kopii objektu, ve kterém byla zavolána.
Dnes si ukážeme první způsob, jak ji naprogramovat. Spočívá ve využití metody
Obejct.toSource, která vrátí řetězec reprezentující zápis objektu v
JavaScriptu. Tento řetězec pak vyhodnotíme globální funkcí eval –
výsledkem bude instance objektu vytvořená podle řetězce a tedy shodná s
předchozím objektem. Zde je kód:
Object.prototype.clone = function() {
return eval(this.toSource());
}
Tato metoda není zrovna čistá (metoda toSource je míněna spíše
jako interní), navíc selhává v případech, kdy objekt vytvoříme konstruktorem a
pak do něj přiřadíme nějaké vlastnosti. Například v následujícím kódu se na
posledním řádku vypíše undefined, protože toSource
vrátí řetězec "({y:5})" a nastavení vlastnosti x v prototypu jaksi
pomine (proč, tomu přesně nerozumím).
function Trida() {};
Trida.prototype = { x: 1 };
a = new Trida();
a.y = 5;
b = a.clone();
document.write(b.x);
Z tohoto důvodu příště zkusíme metodu clone naprogramovat jinou
cestou.