Egy régebbi melós projekt során merült fel a dolog, aztán azóta még nem volt nagyon időm írni róla, pedig akkor eléggé rákattantam a témára. Aztán most, hogy újraírtam a deadlime bejegyzés értékelő rendszerét valami korrektebb formába (azok a kis csillagok jobbra a bejegyzés után...), gondoltam ejtek néhány szót az objektum-orientált JavaScript szépségeiről.
A "JavaScriptben programozás szépségei", mint olyan, nem nagyon merült fel bennem soha, ha ezzel a nyelvvel kellett foglalkoznom (bár ebben biztos az is szerepet játszott, hogy még a különböző keretrendszerek elterjedése előtt az embernek if ágak egész erdejét kellett írnia, hogy a műve végül a főbb böngészőkben működjön). Szerencsére ezen sikerült változtatni.
A dolog alapjait egy, a weblaboron megjelent cikk elég jól leírja, én most inkább egy másik megközelítést szeretnék megemlíteni, amit ha a prototype.js-el együtt használunk, egy sokkal szebb szerkezetet kapunk.
Kezdetben ugye volt nekünk a függvény, mint olyan, amit egy alternatív módon is meg tudtunk adni:
var f = function(param) { alert('param: '+param); }; f('valami');
Aztán van olyan dolog is a JavaScript-ben, hogy asszociatív tömb, amit valahogy így kell elképzelni:
var a = { a : 'a értéke', b : 'b értéke', c : 'c értéke' }; alert(a['a']);
A dolog ott kezd érdekessé válni, hogy ugye minden ilyen tömbelem elérésre létezik egy alternatív módszer is, ami már olyan "objektum-orientált" szerű:
var a = { a : 'a értéke', b : 'b értéke', c : 'c értéke' }; alert(a.a);
Itt jön a gondolat, hogy mi lenne, ha ezt a két módszert összekombinálnánk, és akkor legalább már ez az OOP dolog annyiban megvalósulna, hogy a függvényeket egy csokorba tudjuk gyűjteni:
var c = { f : function(param) { alert('param: '+param); } }; c.f('valami');
Most már mondhatni alakul a dolog, de hát még a példányosítás hiányzik. Itt jönnek a képbe a függvények (tehát ezen a ponton már érdemes a weblabor cikk által nyújtott tudás birtokában lenni), amikkel lehet ilyen perverz dolgokat is művelni:
var f = function(param) { this.out = param; this.alert_me = function() { alert('param: '+this.out); }; }; var p = new f('valami'); p.alert_me();
Na kérem szépen, ez már egészen OOP, már csak helyre kell pofozni, mert ez így nem kicsit csúnya. Tehát, van a minden függvényenek alapból egy prototype tulajdonsága (aminek tökéletesen semmi köze nincs a prototype.js keretrendszerhez), aminek ilyen asszociatív tömb formában szépen meg lehet adni a függvény további tulajdonságait is. Valahogy így:
var c = function(param) { this.out = param; }; c.prototype = { alert_me : function() { alert('param: '+this.out); } }; b = new c('másvalami'); b.alert_me();
A dolog csúnyasága csak annyi, hogy a konstruktor és a többi függvény el van választva egymástól. Ezen segít a prototype.js, aminek van egy Class.create() függvénye. Ennek segítségével az osztályunk initialize() függvénye automatikusan meghívódik új példány készítése esetén, és átadódnak neki a paraméterek:
var c = Class.create(); c.prototype = { initialize : function(param) { this.out = param; } alert_me : function() { alert('param: '+this.out); } }; b = new c('másvalami'); b.alert_me();
Emiatt az egy dolog miatt mondjuk még nem lenne érdemes a prototype.js -t használni, mivel ez a része csak ennyiből áll:
var Class = { create : function() { return function() { this.initialize.apply(this, arguments); }; } };
De mivel egyéb jó tulajdonságokkal is rendelkezik, ezért nézzünk is meg még egy kis példakódot, hogy jobban előjöjjenek a dolog szépségei:
var Gomb = Class.create(); Gomb.prototype = { initialize : function(id) { this.object = $(id); Event.observe( this.object, 'mouseover', this.evt_over.bindAsEventListener(this) ); Event.observe( this.object, 'mouseout', this.evt_out.bindAsEventListener(this) ); Event.observe( this.object, 'click', this.evt_click.bindAsEventListener(this) ); }, evt_over : function(evt) { alert(this.object.id+' mondja: Hurrá, fölöttem van az egér!'); }, evt_out : function(evt) { alert(this.object.id+' mondja: Már nincs :\'('); }, evt_click : function(evt) { alert(this.object.id+' mondja: Köszi, hogy megnyomtál!'); } }; var my_button = new Gomb('id_button');
A használt prototype.js függvényekről további információ: Class.create(), Event.observe(), Function.bindAsEventListener(). Ennyit mára, JavaScriptekben gazdag további szép napot. :)

