Autor Zpráva
Witiko
Profil
Rád bych tu otevřel debatě téma ECMAScriptu v5 a novinek, které přináší už jenom kvůli enormnímu dopadu na výsledný kód ve světle těchto změn. Daná specifikace spatřila světlo světa již roku 2009, přičemž šlo o první oficiální "update" od roku 1999, jelikož 4. verze nebyla vypuštěna údajně kvůli vnitřním rozporům. Ale dost již dějepisu. Co nám tedy ECMA v5 přináší?

Gettery a Settery
Jedná se o interní funkce přichycené na vlastnost objektu. Při zjišťování hodnoty vlastnosti je pak navrácena návratová hodnota getter funkce, při změně/přiřazení hodnoty je pak zavolána setter funkce. Toto umožňuje mnohem vyšší eleganci jak vnitřního kódu, tak interface. Bez těchto funkcí mohly být proměnné použité k uchování dat, nyní je zde však nový způsob využití a to jako přístupové proměnné - tento koncept je mnohdy mnohem přehlednější a šikovnější, než volání funkcí a umožňuje vyšší úroveň abstraktizace, viz. Chamurappiho definice vlastnosti innerText.

Schématická ukázka použití:
jména - setter = function(jméno) {
  seznam.push(jméno);
}

jména - getter = function() {
  return "V seznamu se nachází " + seznam.length + " lidí.";
}

var seznam = new Array();
alert(jména); // - V seznamu se nachází 0 lidí
jména = "Jan Novák";
alert(jména); // - V seznamu se nachází 1 lidí


Již před oficiální podporou zde byly a stále jsou neoficiální funkce od Mozilly, těmi jsou:
Objekt.prototype.__defineGetter__ - Volání: Objekt.__defineGetter__(vlastnost, funkce)
Objekt.prototype.__defineSetter__ - Volání: Objekt.__defineSetter__(vlastnost, funkce)
Objekt.prototype.__lookupGetter__ - Volání: Objekt.__lookupGetter__(vlastnost)
Objekt.prototype.__lookupSetter__ - Volání: Objekt.__lookupSetter__(vlastnost)

__define funkce připojují danou s/getter funkci, __lookup ji navrací. Kromě tohoto způsobu zápisu tu je i jiný, oku příjemnější, leč syntaxi odporující a výjimku v případě nepodpory vyvolávající způsob definice:

Objekt = {
    get vlastnost(){
        return ...;
    },
    set vlastnost(val){
        ... = val;
    }
};


Specifikace ECMAScriptu nám to samé umožňuje pomocí speciálních funkcí na definici jednotlivých vlastností objektu, funkce se nazývá Object.defineProperty(objekt, vlastnost, deskriptor) a umožňuje velmi detailně nastavovat chování vlastností objektu.

objekt - modifikovaný objekt
vlastnost - název vlastnosti
deskriptor - objekt obsahující definici chování a hodnotu vlastnosti:
{
value: "test",
- hodnota vlastnosti
get: function() {return ...},
- getter funkce
set: function(value) {...},
- setter funkce
writable: true,
- hodnota vlastnosti je / není editovatelná, jedná se o náhradu dřívějšího konceptu konstant
enumerable: true,
- vlastnost je / není enumerovatelná (spočetná) - tzn. ne / ukáže se při průchodu objektem pomocí for(proměnná in objekt)
configurable: true
- ostatní nastavení hodnoty jsou / nejsou editovatelná, vlastnost je / není smazatelná
}


Veškeré výše zmíněné vlastnosti deskriptoru jsou volitelné. Prostý zápis je samozřejmě stále možný, nicméně má tímto člověk mnohem větší možnosti manipulace. Další funkce nově v ECMAScriptu v5 zabývající se vlastnostmi objektů:

Object.defineProperties( objekt, vlastnosti ) - To samé, jako výše zmíněná funkce s tím rozdílem, že je pomocí ní možné definovat vlastnosti hromadně. Druhým argument je objekt ve formátu {vlastnost: deskriptor, vlastnost: deskriptor, ...}.
Object.preventExtensions( objekt ) - Zabrání přidávání dalších vlastností
Object.isExtensible( objekt ) - Zjistí, je-li povoleno přidávání dalších vlastností
Object.keys( objekt ) - Navrátí pole všech spočetných vlastností objektu, alternativa k for(proměnná in objekt) cyklu
Object.getOwnPropertyNames( objekt ) - Navrátí pole všech vlastností objektu
Object.create( prototyp, vlastnosti ) - V jednom volání rozšíří nově vytvořenou instanci o další vlastnosti, ty jsou ve stejném formátu jako v případě Object.defineProperties. Volání: var honza = Object.create(new Zaměstnanec(), {jméno:{value:"Jan"},příjmení:{value:"Novák"}});
Object.seal( objekt ) - Změní objektu configurable na false a zabrání přidávání dalších vlastností. Nastavení vlastností je neměnné, vlastnosti samotné nelze přidávat ani mazat, ale je možné editovat jejich hodnoty.
Object.isSealed( objekt ) - Kontroluje přítomnost výše zmíněného stavu
Object.freeze( objekt ) - Změní objektu configurable a writable na false a zabrání přidávání dalších vlastností. Nastavení vlastností je neměnné, vlastnosti samotné nelze přidávat, mazat ani editovat. Vzniká zcela neměnný objekt.
Object.isFrozen( objekt ) - Kontroluje přítomnost výše zmíněného stavu
Object.getOwnPropertyDescriptor( objekt, vlastnost ) - Kontroluje přítomnost výše zmíněného stavu

Já osobně jsem z těchto nových možností poměrně nadšený, jelikož umožňují mnohem vyšší úroveň kontroly nad interface objektů a Settery a Gettery jsou vítaným přídavkem do syntaxe. Osobně se však divím jedné věci a to sice proč zde není i podpora Deleterů - tzn. funkce zavolaná při smazání dané vlastnosti. To by dozajista také našlo uplatnění, napadá mě jich zpatra hned několik.

Problémem výše zmíněného výčtu je však podpora, která, ačkoliv například v případě s/getterů velmi slušná, je u starších verzí prohlížečů stále nenasimulovatelná, což je problém, který brání využití u seriózních projektů. Podpora je dle mého vlastního pozorování následující (velmi vágní, citelně postrádá data, poprosím o případné doplnění / opravu):

Nestandardní funkce od Mozilly:
- Opera 11
- Firefox 3.X+
- Webkit

Metody ECMAv5:
- Firefox 4
- Webkit
- Internet Explorer 8+ (ale pouze Object.defineProperty s omezením vstupního objektu na window / DOM Element)

Nutnost obcházení / lepení přístupových vlastností s gettery a settery přímo na globální objekt window tak trochu znemožňuje elegantní podporu ve všech prohlížečích.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: