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.