A prototype tulajdonság

Az előzőekben láthattuk hogyan adhatunk létező objektumoknak újabb tulajdonságokat. A következőkben a prototípus tulajdonságról lesz szó, amelynek segítségével új tulajdonságokat tudunk hozzárendelni egy osztály összes előfordulásához.

var o1,o2 = null;

function MyObject(name){ // konstruktor függvény (object constructor)
    this.name = name;
}


o1 = new MyObject("obj1");
//o1.TellName(); // ezen a ponton meg nem hívható meg a 'TellName' metódus 

MyObject.prototype.TellName = function(){
    alert("Hi. I am "+ this.name);
}

o2 = new MyObject("obj2");


o1.TellName(); // obj1
o2.TellName(); // obj2

Minden egyes függvény objektum rendelkezik egy kitüntetett szereppel bíró prototype nevű tulajdonsággal, amely egy objektum és alapértelmezett értéke a beépített Object objektum. A MyObject nevű konstruktor függvény létrehozásakor a függvény prototype tulajdonsága egy üres Object. Ezt az üres objektumot bővítjük egy új metódussal. Ezen ponton túl bármilyen MyObject konstruktor függvényből példányosított objektum rendelkezni fog a TellName() nevű metódussal, függetlenül attól, hogy az objektum a kódban hol volt létrehozva (az o1 objektum akkor lett létrehozva, mielőtt még a MyObject konstruktor függvény prototípusához hozzáadtuk a TellName metódust). A prototípus objektum tagjai publikusak, így az objektumunkhoz újonnan hozzáadott metódus is publikus.

A prototype tulajdonsággal osztálytagokat (más néven statikus tagok; Jávában static kulcsszó) tudunk adni egy osztálynak. Ez azt jelenti, hogy a konstruktor függvény prototípusához adott metódusok és tulajdonságok a memóriában csak egy példányban léteznek.

function MyObject(){ // konstruktor függvény (object constructor)
    ++MyObject.prototype.instanceCounter;
    alert('Ez a(z) '+ this.instanceCounter +". példány.");
}

MyObject.prototype.instanceCounter = 0;

o1 = new MyObject(); // Ez a(z) 1. példány.
o2 = new MyObject(); // Ez a(z) 2. példány.

alert("nb of instances: "+ o2.instanceCounter); // nb of instances: 2

A fenti kód egy olyan konstruktor függvényt mutat be, amely számolja a példányok számát. Amikor a MyObject függvényt konstruktorként használjuk, és segítségével létrehozunk egy objektumot, az instanceCounter változó értéke növelve van egyel.

Az olvasó két dologra is figyelmes lehet. Amikor a példányszámláló értéke növelve van miért hivatkozunk rá MyObject.prototype.instanceCounter módon this.instanceCounter helyett. Egy sorral lejjebb pedig this.instanceCounter módon hivatkozunk a példányváltozóra, ami helyes értéket ad vissza. A kérdés megválaszolásához meg kell érteni hogyan is történik a tulajdonság hivatkozások feloldása (mi is történik akkor, amikor használjuk vagy beállítjuk azok értékét). Valahányszor a kódban az objektum olyan tulajdonságára hivatkozunk, ami nem létezik, a JavaScript a tulajdonságot automatikusan a MyObject.prototype-ban próbálja megkeresni. Se az o1 se az o2 objektumok nem rendelkeznek instanceCounter tulajdonsággal, így amikor arra hivatkozunk a this referenciával (this.instanceCounter), a tulajdonság az objektum prototípus láncában lesz keresve. Itt létezik is ilyen nevű tulajdonság, így a tulajdonság értékének kiolvasása lehetséges this.instanceCounter kifejezéssel is.

Az írásra más szabály érvényes: amennyiben az objektumban már létezik az adott nevű tulajdonság, akkor annak értéke felülíródik, amennyiben nem létezik, akkor létrejön egy új a megadott névvel és értékkel. Ha tehát a példányszámláló értékét ++this.instanceCounter utasítással növeltük volna, egy új példányváltozó jött volna létre undefined kezdeti értékkel.

A következő kódrészlet is bizonyítja, hogy a prototype tulajdonsággal nem lehet átírni a konstruktor függvényben deklarált tulajdonságokat vagy metódusokat

function class Foo(){
    this.bar = 1;
}
Foo.prototype.bar = 0;

var objFoo = new Foo();
alert(objFoo.bar); // 1

A prototype tulajdonságot használhatjuk a JavaScript beépített objektumainak bővítésére is. Például hasznos metódusokkal bővíthetjük az Array objektumot:

Array.prototype.Reverse = function (i1, i2){
    var temp = this[i1];
    this[i1] = this[i2];
    this[i2] = temp;
}

A fenti kód a tömb objektumot bővíti egy Reverse metódussal, amely két elem felcserélésére szolgál. Ezután minden tömb-objektum támogatni fogja 2 elem felcserélését.

var aNevek = new Array("Janos", "Peter", "Bela");
aNevek.Reverse(0,1);
alert(aNevek.join(",")); // Peter, Janos, Bela