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