A JavaScript prototípus-alapú öröklődés működése a színfalak mögött

A JavaScript alapvetően különbözik a hagyományos osztályalapú (class-based) objektum-orientált nyelvektől, mint amilyen a Java, a C# vagy a C++. Bár a modern ECMAScript szabványok (ES6) bevezették a class kulcsszót, fontos megérteni, hogy a JavaScript a háttérben továbbra is egy prototípus-alapú (prototype-based) nyelv.

Mi az a Prototípus-lánc (Prototype Chain)?

Minden JavaScript objektum rendelkezik egy titkos belső tulajdonsággal (ezt a nyelv specifikációjában [[Prototype]]-nak, a böngészőkben gyakran __proto__-nak nevezik), amely egy másik objektumra mutat. Ez a másik objektum az ő prototípusa.

Amikor megpróbálunk elérni egy tulajdonságot vagy metódust egy objektumon, a JavaScript motor először magán az objektumon keresi azt. Ha nem találja, automatikusan "fellép" a prototípus-láncon (prototype chain), és megnézi a szülő objektumot. Ezt a folyamatot egészen addig ismétli, amíg el nem éri a lánc végét. A lánc vége szinte mindig a beépített Object.prototype, aminek a prototípusa már null.

Gyakorlati példa a prototípus használatára

Képzeljük el, hogy egy webes játékot fejlesztünk, ahol sok játékos (objektum) van. Ha minden játékoshoz külön hozzárendelnénk a funkciókat, hamar elfogyna a memória.

// Konstruktor függvény
function Fejleszto(nev, nyelv) {
    this.nev = nev;
    this.nyelv = nyelv;
    // ROSSZ MEGOLDÁS: this.bemutatkozik = function() { ... }
}

// JÓ MEGOLDÁS: Metódus hozzáadása a prototípushoz a memóriahatékonyság érdekében
Fejleszto.prototype.bemutatkozik = function() {
    return "Szia, a nevem " + this.nev + " és " + this.nyelv + " nyelven kódolok.";
};

const peter = new Fejleszto("Péter", "JavaScript");
const anna = new Fejleszto("Anna", "Python");

console.log(peter.bemutatkozik()); // Szia, a nevem Péter...
console.log(anna.bemutatkozik()); // Szia, a nevem Anna...

Ha a bemutatkozik metódust közvetlenül a konstruktoron belül definiáltuk volna a this.bemutatkozik = ... formában, akkor minden egyes új példány (Péter, Anna) létrehozásakor újra és újra létrejönne a függvény a számítógép memóriájában. A prototípus használatával a metódus csak egyszer jön létre a Fejleszto.prototype objektumon, és minden példány közösen osztozik rajta.

Összegzés

A prototípusok megértése kritikus fontosságú ahhoz, hogy mesteri szintre emeljük a JavaScript tudásunkat. Bár az újabb ES6 szintaxis (a class) elfedi előlünk ezt a mechanizmust, a háttérben futó motor továbbra is pontosan ezeket a prototípus-láncokat építi fel és használja. A prototípusok biztosítják a JavaScript rendkívüli rugalmasságát és memóriahatékonyságát.

Gyakran Ismételt Kérdések (GYIK)

Mi a különbség a __proto__ és a prototype között?

A prototype a konstruktor függvények (pl. Fejleszto) saját tulajdonsága, amely meghatározza, hogy az ezen függvénnyel létrehozott új objektumok milyen prototípust kapjanak. A __proto__ (vagy Object.getPrototypeOf()) pedig magának a már létrehozott objektumnak (pl. peter) a belső mutatója a prototípusra.


Ezek is érdekelhetnek: