Objektumok tulajdonságai és metódusai

Egy objektum tulajdonságokból áll. Egy tulajdonságot a neve határozza meg, és tartozik hozzá egy érték. Az értéke lehet egy objektum, primitív érték (undefined, null, boolean, string, number) vagy metódus (Function objektum).

Tegyük fel, hogy létre akarunk hozni egy „fa” objektumtípust. Ennek az objektumtípusnak a Fa nevet akarjuk adni, tulajdonságai a szin, nev, és hang lesznek. Ehhez a következő függvényt kell megírnunk:

function Fa(nev, szin, hang){
    this.nev = nev;
    this.szin = szin;
    this.hang = hang;
}

var fenyoFa = new Fa('fenyo', 'zold', 'susog');

Az összes Fa példány három publikus hozzáférésű tulajdonsággal (példányváltozóval) fog rendelkezni. Kétféle módon is olvashatjuk az objektum tulajdonságát:

fenyoFa.nev = 'lucfenyő';
alert(fenyoFa.nev); // lucfenyő

// vagy

fenyoFa['nev'] = 'lucfenyő';
alert(fenyoFa['nev']); // lucfenyő

A JavaScript a privát láthatóságú példányváltozókat is támogatja. Privát láthatóságú példányváltozókat úgy tudunk létrehozni, hogy a konstruktor függvényben lokális változókat deklarálunk.

function Fa(){
    var nev,
        szin,
        hang;
}

Megjegyzés: A konstruktor függvény paraméterei is privát változók.

var fa1 = new Fa("magas fa", "zold","");
alert(fa1.nev); // hiba; a nev kívülről nem elérhető

A var kulcsszó elhagyása globális változót hoz létre, amennyiben ezzel az azonosítóval még nem létezik globális változó[15]. Ha már van ilyen nevű globális változó, akkor annak értéke átíródik. Erre nagyon oda kell figyelni, mert a var kulcsszó kihagyása nagyon nehezen felfedezhető hibák okozója lehet.

function ValamilyenFüggvény(){
    i = 0; // véletlenül elhagytuk a var kulcsszót a sor elejéről
    return "";
}

var i;
for(i=0; i < 10; i++){
    ValamilyenFüggvény();
}

A fenti hibát könnyű észrevenni, hiszen egy végtelen ciklus keletkezik.

Privát példánymetódusokat is létre tudunk hozni. Mint azt korábban említettem, egy függvény létrehozásakor egy változó keletkezik a függvény nevével. Egy függvényen belül deklarálhatunk további ún. belső függvényeket, melyek hasonlóan a lokális változókhoz privát láthatóságúak lesznek.

function getNev3(){
    alert(nev);
}

function Kulso(){
    var nev = "lokalis valtozo"; // privát változó

    function Belso(){ // privát metódus
        alert(nev); // lokalis változó
    }

    // function kulcsszóval definiált függvény
    this.getNev = function (){ // publikus metódus
        alert(nev); // lokalis valtozo
    };

    // Function konstruktorral létrehozott függvény
    this.getNev2 = new Function("alert(nev);"); // publikus metódus – nem látja a nev változót
    // csupán a referenciát a függvényre rendeljük hozzá a getNev3 tulajdonsághoz
    this.getNev3 = getNev3;

    alert(typeof Belso); // function
}

JavaScriptben minden kód egy úgynevezett futási környezetben (execution context) hajtódik végre. A program futása a globális futási környezetben indul, majd amikor meghívunk egy függvényt, akkor egy új jön létre, és egészen addig ez lesz érvényben, amíg egy újabb függvény hívására kerül sor, vagy visszatérünk az adott függvényből.

Minden egyes függvény objektum rendelkezik egy [[scope]] nevű belső tulajdonsággal, ami az objektum létrehozásakor kap értéket attól függően, hogy az milyen környezetben jön létre. Egy futási környezetbe való belépéskor sok minden történik (akit részletesebben érdekel a téma, annak ajánlom figyelmébe a fejezet végén található linkeket), én most csak a láthatósági listára (scope chain) térnék ki. Amikor egy függvényt meghívunk, egy új futási környezet jön létre, ami magába foglalja a láthatósági lista létrehozását is. A láthatósági lista egy objektum lista, amely alapján zajlik majd az adott futási környezetben az azonosítók feloldása. Function konstruktorral létrehozott függvény esetén a láthatósági lista csak a globális láthatósági lista, míg a function kulcsszóval definiált függvények esetében az őket létrehozó futási környezet láthatósági listája kerül bele.

A nev értéke kívülről nem lesz elérhető, de tudunk definiálni hozzá getNev(), setNev() metódusokat. A példakódban bemutatott getNev() egy példánymetódus, ami annyit jelent, hogy minden egyes objektum példány esetében a metódus számára külön függvény objektum jön létre. Nagyon sok példány létrehozásakor feleslegesen sok memóriát fog használni a webböngésző (privatTagvaltozo/teszt.html), a prototype tulajdonság igénybevétele előnyösebb memóriahasználat szempontjából (a getNev3 metódus csak egy referenciát tárol a külső függvényre, a külső függvény viszont szennyezi a globális névteret). Ugyancsak érdemes megemlíteni, hogy a getNev() metódussal egy ún. lezárást (lexical closure) hoztunk létre. Ebben az esetben egy ártatlan lezárásról van szó. A későbbiekben látni fogjuk, hogy a lezárások helytelen használata memória szivárgást (memory leak) okozhat egyes böngészőkben. A prototype tulajdonságot és a lezárásokat későbbi fejezetek tárgyalják részletesebben.

Egy objektumhoz utólag is lehet tulajdonságokat és metódusokat hozzáadni.

function Fa(nev, magassag){
    this.nev = nev;
    this.magassag = magassag;
}
var obj1 = new Fa("Akac", 2);
obj1.Bemutatkozas = function (){
    alert("Üdvözlöm. A nevem: "+ this.nev + " es "+ this.magassag +" méter magas vagyok");
};
obj1.Bemutatkozas();

Az obj1 objektum még nem rendelkezett Bemutatkozas nevű tulajdonsággal a hozzárendelés előtt, az a hozzárendeléskor jött létre és értéke egy függvény. Ez az eljárás nincs befolyással más objektumokra, mindig csak egy objektum példányra van hatással. JavaScriptben bármilyen létező objektumot képesek vagyunk utólag bővíteni metódusokkal vagy tulajdonságokkal.

window.document.ujTulajdonsag = "valami ertek";
document.getElementById("domNodeNev").ujTulajdonsag = "valami ertek";

Akár a böngésző szolgáltatta objektumokhoz is képesek vagyunk újabb metódusokat vagy tulajdonságokat hozzárendelni. Ez nagyon hasznos és gyakorta igénybe vett tulajdonsága a JavaScriptnek.