Vissza az előzőleg látogatott oldalra (nem elérhető funkció)Vissza a tananyag kezdőlapjára (P)Ugrás a tananyag előző oldalára (E)Ugrás a tananyag következő oldalára (V)Fogalom megjelenítés (nem elérhető funkció)Fogalmak listája (nem elérhető funkció)Oldal nyomtatása (nem elérhető funkció)Oldaltérkép megtekintése (D)Keresés az oldalon (nem elérhető funkció)Súgó megtekintése (S)

Bevezetés a kliens- és szerveroldali webalkalmazások készítésébe / A JavaScript további nyelvi elemei

Tanulási útmutató

Összefoglalás

Ebben a fejezetben a JavaScript nyelv főleg azon tulajdonságait tekintjük át, amelyben a C-alapú nyelvektől különbözik. Ez a fejezet elsősorban kitekintés, a benne lévő ismeretekre alapvetően nincsen szükség a tananyag megértéséhez, de nagyon ajánlott megismerkedni vele azoknak, akik szeretnének elmélyedni a JavaScript nyelvben. A fejezet végén a JavaScript beépített objektumairól és az időzítőkről van szó, amit mindenkinek illik ismernie.

A JavaScript további nyelvi elemei

Az előző fejezetben áttekintettük a JavaScript nyelv alapjait főleg olyan szempontból, hogy milyen hasonlóság is fedezhető fel a C++ nyelvvel. Ebben a fejezetben egyrészt kiegészítjük az eddigieket, másrészt újabb ismereteket tekintünk át.

Globális függvények

A JavaScript számos globális elérhető függvényt definiál. A következőkben ezek közül tekintjük át a fontosabbakat. A teljes listát a szabvány és a referencia tartalmazza.

Not a Number

Ha egy matematikai művelet eredménye kivezet a számok halmazából, akkor a JavaScript egy speciális számot ad eredményül, ami igazából „nem-szám”, a NaN (Not a Number) értéket. A NaN toxikus hatású, azaz matematikai kifejezésben megjelenve, az is NaN-t ad eredményül. Egyedüli biztos vizsgálata az isNaN() függvénnyel lehetséges.

Forráskód
var sokPenz = 100 * 'kevés pénz';
sokPenz;        // => NaN
sokPenz / 10;   // => NaN
isNaN(sokPenz); // => true

Végtelen

Ha az ábrázolható értéktartományon kívülre vezet egy matematikai műveletek, akkor két speciális számot kaphatunk, a pozitív végtelent (Infinity vagy +Infinity) vagy a negatív végtelent (-Infinity). Vizsgálata az isFinite() függvénnyel lehetséges.

Forráskód
var a = 10/0;
a;              //Infinity
isFinite(a);    //false

Konverziók

Szöveges érték explicit átalakítása számmá a parseInt() és a parseFloat() globális függvényekkel lehetséges. Mindkét függvény első paramétereként az átalakítandó szöveget kell megadni. A parseInt()-nek e mellett második paraméterként azt is meg lehet adni, hogy a szöveget milyen számrendszerű számnak értelmezze. Érdemes ezt a paramétert mindig kitölteni.

Mindkét függvény addig próbálja értelmezni a szöveget, amíg a formátumának megfelelő számokat talál az elején. Ha a szöveg egyáltalán nem alakítható át, akkor NaN lesz az eredmény.

Forráskód
//parseInt
parseInt('123');     //123
parseInt('123', 10); //123
parseInt('0101', 2); //5
parseInt('alma', 10); //NaN
parseInt('5alma', 10); //5
 
//parseFloat
parseFloat('4.54'); //4.54
parseFloat('3.1415 a pi'); //3.1415

Szövegkódolás

Webes alkalmazásokban az információ gyakran kerül tárolásra vagy továbbításra szöveges formátumban. Annak érdekében, hogy a speciális karakterek se okozzanak gondot, megfelelően kódolni szükséges őket. JavaScriptben az encodeURI() és encodeURIComponent() függvények szolgálnak egy kódolatlan szöveg kódolására, és a decodeURI() és decodeURIComponent() függvények egy kódolt szöveg visszanyerésére. Az encodeURI() és decodeURI() függvények teljes URI-k kódolására szolgálnak, feltételezvén, hogy bizonyos karakterek (/, :, ;, ?, #, &) az URI részei, ezért ezeket kihagyják a kódolási folyamatból. Ezzel szemben az encodeURIComponent() és decodeURIComponent() függvények az URI egyes részeinek kódolására valók, ezeknél a fent említett speciális karaktereknek nincs speciális funkciója, azok a szöveg részét képezik.

Forráskód
//Szöveg kódolása és dekódolása
var kod = encodeURIComponent('árvíztűrőtükörfúrógép');
kod;    //"%C3%A1rv%C3%ADzt%C5%B1r%C5%91t%C3%BCk%C3%B6rf%C3%BAr%C3%B3g%C3%A9p"
var dekod = decodeURIComponent(kod);
dekod;  //"árvíztűrőtükörfúrógép"
 
//URI kódolása
encodeURI('http://példa.hu/index.php?sz=Bogyó és Babóca');
//"http://p%C3%A9lda.hu/index.php?sz=Bogy%C3%B3%20%C3%A9s%20Bab%C3%B3ca"
 
//URL küldése paraméterként
var url = encodeURIComponent('http://példa.hu/index.php?sz=Bogyó és Babóca');
//"http%3A%2F%2Fp%C3%A9lda.hu%2Findex.php%3Fsz%3DBogy%C3%B3%20%C3%A9s%20Bab%C3%B3ca"
encodeURI('http://valami.hu/index.php?hova=') + url;
//"http://valami.hu/index.php?hova=http%3A%2F%2Fp%C3%A9lda.hu%2Findex.php%3Fsz%3DBogy%C3%B3%20%C3%A9s%20Bab%C3%B3ca"
Megjegyzés

Szövegek oda-visszakódolásánál találkozhatunk még az escape() és unescape() függvényekkel is. Ezeket azonban a szabvány már nem tartalmazza, elavultak, és használatuk nem javasolt.

Vissza a tartalomjegyzékhez

Függvényekről bővebben

Az előző fejezetben láthattuk, hogy JavaScriptben hogyan lehet függvényeket létrehozni. Akkor főleg olyan szemmel néztük meg őket, hogy a C alapú nyelveknél megismert függvényeket hogyan tudjuk JavaScriptben megvalósítani. Láthattuk, hogy a szintaxis ebben az esetben eltérő az ott megismertektől, ami főleg a JavaScript nyelv gyengén típusosságából adódik.

A JavaScriptbeli függvények azonban sokkal sokoldalúbbak, amelyek a nyelv funkcionális oldalát biztosítják. A következőkben áttekintjük a JavaScript függvények néhány további tulajdonságait.

Hivatkozás és meghívás

Egy függvény meghívása úgy történik, hogy a neve után gömbölyű zárójelben megadunk valahány paramétert (akár egyet sem). Ha azonban nincsen zárójel a függvény neve után, akkor csak hivatkozunk a függvényre, azaz függvényreferenciát használunk. Egy függvényreferencia sok helyen megjelenhet (ld. lentebb a függvényliterálnál, vagy később az időzítőknél és eseménykezelőknél), legegyszerűbb esetben egy függvényt másképpen nevezünk el, ahogy az alábbi példa is mutatja:

Forráskód
//Függvénydeklaráció
function ketszerez(a) {
    return a * 2;
}
//Függvényreferencia átadása
var duplaz = ketszerez;
//Függvény meghívása
duplaz(21); //42

Itt a duplaz változó megkapta ugyanannak a függvénynek a referenciáját, mint amire a ketszerez mutatott. Így a duplaz-t meghívva a ketszerez() függvény fut le.

Formális és aktuális paraméterek viszonya

Az aktuális és formális paraméterek száma nem kell, hogy megegyezzen. Ha kevesebb aktuális paramétert adunk meg, akkor az értéket nem kapó formális paraméterek értéke undefined lesz. Ha több aktuális paramétert adtunk meg, mint ahány formálisat soroltunk fel, akkor a függvényen belül egy arguments nevű tömbszerű objektumon keresztül lehet őket elérni. Az aktuális paraméterek számát ennek length tulajdonságával lehet lekérdezni. Visszatérési érték hiányában a függvény undefined-dal tér vissza.

Forráskód
function proba(a, b) {
    console.log('a =', a);
    console.log('b =', b);
    console.log('arguments =', arguments);
}
 
//Aktuális és formális paraméterek száma megegyezik
proba(1, 2);
// => a = 1
// => b = 2
// => arguments = [1,2]
 
//Kevesebb aktuális paraméter
proba(1);
// => a = 1
// => b = undefined
// => arguments = [1]
 
//Több aktuális paraméter
proba(1, 2, 3)
// => a = 1
// => b = 2
// => arguments = [1,2,3]
 
//return hiányában a visszatérési érték undefined
console.log(proba(1, 2));   // => undefined

Az arguments tömb lehetőséget ad általános függvények írására is. Tekintsünk egy olyan függvényt, amely a paraméterül megkapott számok átlagát adja vissza.

Forráskód
//Az átlag függvény definíciója
function atlag() {
    var s = 0;
    var n = arguments.length;
    for (var i = 0; i < n; i++) {
        s += arguments[i];
    }
    return s / arguments.length;
}
 
//Az átlag függvény használata
atlag(8, 9);        //8.5
atlag(1, 2, 3, 4);  //2.5
atlag();            //NaN

A függvényliterál

A függvényeket eddig olyan szempontból vizsgáltuk, hogy hogyan lehet őket létrehozni, azaz deklarálni, és meghívni. Ennek során megismerkedtünk a függvénydeklarációval, ami a függvénylétrehozás fent használt módszere.

JavaScriptben azonban a függvényeket az teszi sokoldalúvá, hogy a függvény önmagában egy kifejezés, és mint ilyen, más kifejezésekben megjelenhet. Mivel a többi adattípushoz tartozott egy olyan forma, amellyel kifejezésekben megjelenhetnek – ezt neveztük literálformának –, akképpen a függvényekhez is tartoznia kell egy literálformának, ha ő is kifejezésekben szerepelhet. Ez a függvényliterál, és a következőképpen néz ki:

Forráskód
function (par1, par2) {
    //JavaScript kód
}

A függvényliterált nevezzük még függvénykifejezésnek és névtelen függvénynek is.

A függvény mint első osztályú objektum

A függvény kifejezés mivolta azt jelenti, hogy bármilyen kifejezésben megjelenhet. Ezt úgy is nevezik, hogy a függvény első osztályú objektum. Legegyszerűbb ezt úgy elképzelnünk, hogy ahol például egy számliterált használnánk, oda függvényliterált is írhatunk. Ekként egy függvényliterál dinamikusan bárhol létrehozható, és szerepelhet például

Forráskód
//////////////////////////////////////////
// Számliterál különböző kifejezésekben //
//////////////////////////////////////////
 
//Értékadás
var a = 42;
 
//Objektum adattagja
var obj = {
    mezo1: 42
};
 
//Függvényparaméter
function fv(par) {
    console.log(par);
}
fv(42);
 
//Függvény visszatérési értéke
function fv() {
    return 42;
}
 
//////////////////////////////////////////////
// Függvényliterál különböző kifejezésekben //
//////////////////////////////////////////////
 
//Értékadás
var a = function(a, b) {
    return a + b;
};
 
//Objektum adattagja
var obj = {
    mezo1: function(a, b) {
        return a + b;
    }
};
 
//Függvényparaméter
function fv(f, a, b) {
    console.log(f(a, b));
}
fv(function(a, b) {
    return a + b;
}, 10, 32);
 
//Függvény visszatérési értéke
function fv() {
    return function(a, b) {
        return a + b;
    };
}

Függvénykifejezés és függvénydeklaráció

Ha a függvényliterált értékadásban használjuk, akkor a függvénydeklaráció mellett megjelenik a függvények egy másik létrehozási formája is, amely függvénykifejezést használ. A kétféle létrehozási forma apróbb eltérésekkel – amelyekre most nem térünk ki – egyenértékű. Hívásukban különbség nincs.

Forráskód
//Függvénydeklaráció
function osszead(a, b) {
    return a + b;
}
 
//Függvénykifejezéssel
var osszead = function (a, b) {
    return a + b;
};
 
//Hívásuk
osszead(10, 32);    //42

Függvény mint paraméter

A függvény mint kifejezés megjelenhet függvények paramétereként is, amellyel igen sokoldalú és általános függvények készíthetők. Ekkor a függvény meghívhatja a paraméterként megadott függvényt, így a függvénynek logika adható át a paraméterként megjelenő függvény segítségével.

Ennek segítségével például könnyen általánosíthatjuk azokat a programozási tételeinket, amelyek valamilyen T tulajdonságú elemmel dolgoznak. Itt a T egy olyan függvény, amely a tételben általánosan jelenik meg, és a konkrét feladattól függően fejthető ki. Az előző részben leírt lineáris keresés például így írható át:

Forráskód
function kereses(x, T) {
    var i = 0;
    while (i < x.length && !T(x[i])) {
        i++;
    }
    return {
        vane: i < x.length,
        sorsz: i
    };
}

Ha negatív elemet szeretnénk keresni számok sorozatában, az így nézhet ki:

Forráskód
function negativE(p) {
    return p < 0;
}
 
var tomb = [1, 3, -2, 8];
console.log(kereses(tomb, negativE));

Ha páratlan szám keresése a cél, akkor csak a T függvényt kell átírnunk.

Forráskód
function paratlanE(p) {
    return p % 2 !== 0;
}
 
var tomb = [1, 3, -2, 8];
console.log(kereses(tomb, paratlanE));

A függvény mint visszatérési érték

Igen összetett feladatok oldhatók meg azokkal a függvényekkel, amelyek függvényeket adnak vissza. Ennek részletesebb tárgyalása nem tartozik e tananyag keretei közé, példaképpen azonban nézzünk meg egy egyszerű esetet, amely során egy függvény a karakterként megadott operátor alapján a megfelelő műveletet elvégző függvényt adja vissza:

Forráskód
function muveletKeszito(op) {
    if (op === '+') {
        return function (a, b) {
            return a + b;
        };
    }
    else if (op === '*') {
        return function (a, b) {
            return a * b;
        };
    }
}
 
//Összeadó függvény készítése
var muvelet = muveletKeszito('+');
muvelet(10, 32);    //42
 
//Szorzó függvény készítése
var muvelet = muveletKeszito('*');
muvelet(10, 32);    //320

Függvényliterál és függvényreferencia

A függvényliterál minden esetben helyettesíthető függvényreferenciával. Ez azt jelenti, hogy nem kell minden esetben a függvény felhasználási helyén megjelennie a névtelen függvénynek. Azt külön definiálhatjuk máshol – vagy függvénydeklarációval, vagy függvénykifejezéssel –, és az adott helyen csak hivatkozunk a függvényre a nevén keresztül. Ez fentebb már többször előjött, például a Hivatkozás és meghívás vagy a Függvény mint paraméter fejezetben. Az előző fejezetbeli muveletKeszito() függvény kódját ezzel olvashatóbbá tehetjük úgy, hogy a két visszaadandó függvényt külön definiáljuk, és visszaadáskor csak hivatkozunk rájuk:

Forráskód
function osszead(a, b) {
    return a + b;
}
 
var szoroz = function (a, b) {
    return a * b;
}
 
function muveletKeszito(op) {
    if (op === '+') {
        return osszead;
    }
    else if (op === '*') {
        return szoroz;
    }
}

A fenti példában szándékosan definiáltuk különbözőképpen az osszead() és szoroz() függvényt, demonstrálandó azt, hogy a hivatkozás független a létrehozás módjától.

Önkioldó függvény

Érdekességképpen megemlíthetjük, hogy a függvényliterál és -hivatkozás felcserélésének van még egy érdekes következménye. Függvény hívásakor a függvényhivatkozás után gömbölyű zárójelet kell tenni. A függvényhivatkozás azonban helyettesíthető a függvényliterállal, azaz a függvény helyben definiálásával. Ekkor a definiált függvényt rögtön meg is hívjuk, a szakirodalom az ilyen függvényeket önkioldó függvényeknek nevezi.

Forráskód
//Függvény definiálása
var szoroz = function (a, b) {
    return a * b;
}
 
//Függvény meghívása
szoroz(6, 7);   //42
//vagy hangsúlyozandó, hogy itt függvényreferencia van
(szoroz)(6, 7); //42
 
//Függvényhivatkozást függvényliterállal helyettesítve
(function (a, b) {
    return a * b;
})(6, 7);       //42

Önkioldó függvényeket sok helyen alkalmazzák, de ennek részletes tárgyalása nem ennek a tananyagnak része.

Vissza a tartalomjegyzékhez

Objektumok további részletei

Az előző fejezetben a JavaScript objektumokról megállapítottuk, hogy kulcs-érték párok gyűjteménye. Ott elsősorban olyan szemmel tekintettünk rájuk, hogy milyen hasonlóság fedezhető fel más nyelvekkel összevetve, és megállapítottuk, hogy leginkább a rekordnak (a C++-beli struct-nak) feleltethetők meg. Természetesen jó pár különbségre is fény derült. A JavaScript objektumok abszolút dinamikusak, értékei tetszőlegesen módosíthatók, bővíthetők, törölhetők.

Az alábbiakban a JavaScript objektumok további tulajdonságaival ismerkedünk meg, és látni fogjuk, milyen fontos szerepet töltenek be a nyelvben.

Metódusok

A kulcs-érték párokról megjegyeztük, hogy a kulcs alapvetően tetszőleges azonosító lehet; ha azonban az azonosító foglalt kulcsszó vagy nem felel meg az azonosító szintaktikai szabályainak, akkor szövegként kell megadnunk. Az értékek elemi vagy összetett adattípusok is lehetnek, ezeket tulajdonságoknak hívjuk. Nem beszéltünk azonban arról, hogy érték lehet függvény is, ebben az esetben metódusról beszélünk.

A JavaScript objektumok tehát tulajdonságok és metódusok gyűjteménye, és ilyen szempontból sokkal jobban hasonlítanak az objektum-orientált nyelvek objektumaira, amelyek ugyancsak adattagokat és metódusokat tartalmaznak.

A metódusokat egyszerűen úgy adjuk meg, hogy az érték helyére egy függvényliterált írunk. A metódus meghívása az objektum megfelelő kulcsán keresztül megkapott függvény meghívásából áll.

Forráskód
//Objektum létrehozása
var matyi = {
    kor: 1.5,
    nev: 'Mátyás',
    sir: function () {
        console.log('Oáááá');
    }
};
 
//Objektum adattagjainak elérése
matyi.kor;      //1.5
matyi.nev;      //"Mátyás"
 
//Objektum metódusának meghívása
matyi.sir();    //"Oáááá"

A metódusoknak természetesen lehetnek paraméterei is. Tegyük fel, hogy matyi beszélni tanul, és visszamond mindent, amit hall.

Forráskód
//matyi objektum bővítése a beszel metódussal
matyi.beszel = function (szo) {
    console.log(szo);
}
 
//A beszel metódus meghívása
matyi.beszel("csacsi");     //"csacsi"
matyi.beszel("pillangó");   //"pillangó"

Egy metóduson belül az objektumra hivatkozni a this kulcsszóval lehet. Ezen keresztül elérhetőek az objektum tulajdonságai és metódusai. Egészítsük ki a matyi objektumot egy bemutatkozas() metódussal, amely kiírja a konzolra a nevet.

Forráskód
//matyi objektum bővítése a bemutatkozas metódussal
matyi.bemutatkozas = function() {
    console.log(this.nev + " vagyok.")
}
 
//Az új metódus meghívása
matyi.bemutatkozas();   //"Mátyás vagyok"

Minden objektum

JavaScriptben az objektumok különösen fontos szerepet játszanak. A vezérlési szerkezeteken kívül tulajdonképpen minden objektum. Még a függvények is objektumok, sőt az elemi adattípusok is tudnak objektumként viselkedni, ahogy majd lentebb látjuk.

Az ECMAScript szabvány a következő típusokat különbözteti meg:

Az első öt típus az előző fejezetből ismerős lehet. Ezek az elemi adattípusaink. Minden további összetett típus az objektum alá tartozik. Így például a függvény egy olyan objektum, amelynek futtatható a kódja. A tömb olyan objektum, amelynél a kulcsok egész típusúak és a length paraméternek kitüntetett szerepe van, mert az mindig eggyel nagyobb, mint a legnagyobb egész index.

A nyelvnek azon tulajdonsága, hogy szinte minden objektum, párosulva azzal, hogy ezek az objektumok dinamikusak, nagyon sokoldalúvá teszi a nyelvet. Ennek részleteibe ez a tananyag nem megy bele, csupán felvillant pár érdekes gondolatébresztő példát.

Elemi adattípusok mint objektumok

Elemi adattípust úgy tudunk objektumként használni, hogy az értéket tároló változó neve mögé pontot leírva valamelyik kulcsára hivatkozunk. Ilyenkor az értelmező az elemi adattípust objektummá alakítja, más szóval becsomagolja. A három elemi adattípusnak, a logikainak, a számnak és a szövegnek három csomagolóobjektuma van, a Boolean, a Number és a String. Ez utóbbiak lentebb ki lesznek fejtve, most csak nézzünk egy példát az elemi adattípusok objektumként való használatára. A szövegeknek például számos metódusa létezik, amelyekkel az adott szöveg feldolgozható. Ha például egy szöveget nagybetűssé szeretnénk alakítani, akkor a toUpperCase() metódust kell meghívnunk.

Forráskód
var sz = 'alma';
sz.toUpperCase();       //"ALMA"
 
//vagy egyben
'alma'.toUpperCase();   //"ALMA"

Ha már nincsen szükség a csomagolóobjektumra, akkor az értékek újra elemi adattípusként lesznek ábrázolva. Ennek például az a következménye, hogy például egy primitív adattípust ugyan bővíthetünk további tulajdonságokkal, de ezeket visszanyerni nem tudjuk, mert közben a csomagolóobjektum, amihez felvettük azt, megszűnik.

Forráskód
var a = 42;
a.ujadattag = 'valami';
a.ujadattag;    //undefined

Objektumok típusai

A JavaScriptben háromféle objektumtípust különböztetünk meg:

A következőkben először a felhasználói, majd a beépített objektumokkal fogunk foglalkozni.

Vissza a tartalomjegyzékhez

Felhasználói objektumok létrehozása

Objektumok létrehozásával már az előző részben és most is foglalkoztunk. Láthattuk, hogy új objektumot létrehozni az objektumliterállal lehet, amibe aztán tetszőleges adattagot és metódust felvehetünk. Tekintsük például az alábbi david objektumot, amelybe felvettük ennek a gyermeknek a nevét és korát, valamint két cselekvéséhez tartozó metódust.

Forráskód
//david objektum létrehozása
var david = {
    nev: 'Dávid',
    kor: 4,
    bemutatkozik: function () {
        console.log('A nevem: ' + this.nev);
    },
    alszik: function () {
        console.log('Zzzzzz...');
    }
};
 
//Használata
david.nev;              //"Dávid"
david.bemutatkozik();   //"A nevem: Dávid"
david.alszik();         //"Zzzzzz..."

Mit csináljunk akkor, ha még egy zsofi objektumra is szükségünk van ugyanilyen adattagokkal és metódusokkal, csak az adattagok értékei mások? Egyik lehetőség az, hogy lemásoljuk a david objektumot, és átírjuk az adattagok értékeit. Könnyen beláthatjuk, hogy ez a módszer sok hasonló objektum esetében nem túl hatékony: a kód hossza megnövekszik, a másolások számának növekedtével pedig a hibázás lehetősége is egyre nagyobb lesz.

A másik lehetőség, hogy bevezetünk egy olyan függvényt, ami ilyen felépítésű objektumokat „készít”, és ad vissza. Az ilyen függvényeket objektumgenerálóknak nevezzük.

Forráskód
//Objektumgeneráló függvény
function gyerek(nev, kor) {
    return {
        nev: nev,
        kor: kor,
        bemutatkozik: function () {
            console.log('A nevem: ' + this.nev);
        },
        alszik: function () {
            console.log('Zzzzzz...');
        }
    };
}
 
//Használata
var david = gyerek('Dávid', 4);
var zsofi = gyerek('Zsófia', 7);
david.bemutatkozik();   //"A nevem: Dávid"
zsofi.bemutatkozik();   //"A nevem: Zsófia"

A JavaScriptben lehetőség van ugyanennek a funkcionalitásnak az elérésére más módon, mely szándékosan a C++ vagy a Java nyelv példányosítási mechanizmusához hasonlít. Ebben az esetben ún. konstruktorfüggvényeket definiálunk, és a new operátor segítségével hozzuk általuk létre az objektumainkat. A konstruktorfüggvényen belül az adattagokat és a metódusokat a this objektumhoz kell felvenni. A konstruktorfüggvényeket hagyományosan nagy kezdőbetűvel írjuk, így megkülönböztetendő a többi függvénytől.

Forráskód
//Konstruktorfüggvény
function Gyerek(nev, kor) {
    this.nev = nev;
    this.kor = kor;
    this.bemutatkozik = function () {
        console.log('A nevem: ' + this.nev);
    };
    this.alszik = function () {
        console.log('Zzzzzz...');
    };
}
 
//Használata
var david = new Gyerek('Dávid', 4);
var zsofi = new Gyerek('Zsófia', 7);
david.bemutatkozik();   //"A nevem: Dávid"
zsofi.bemutatkozik();   //"A nevem: Zsófia"

Az utolsó két megoldásnak közös hibája az, hogy ahány objektumot létrehoznak, annyi új függvény is létrehozásra kerül a metódusaiknál. Ennek a problémának egyik megoldása az lehet, hogy a függvényeket külön kiemeljük, és az objektumok létrehozásánál csak hivatkozunk rájuk. Az objektumliterálos létrehozásnál ez a következőképpen nézhet ki:

Forráskód
//Függvények kiemelve
function bemutatkozik() {
    console.log('A nevem: ' + this.nev);
}
function alszik() {
    console.log('Zzzzzz...');
}
 
//Objektumgeneráló függvény
function gyerek(nev, kor) {
    return {
        nev: nev,
        kor: kor,
        bemutatkozik: bemutatkozik,
        alszik: alszik
    };
}
 
//Használata
var david = gyerek('Dávid', 4);
var zsofi = gyerek('Zsófia', 7);
david.bemutatkozik();   //"A nevem: Dávid"
zsofi.bemutatkozik();   //"A nevem: Zsófia"

Ennek a megoldásnak a hátránya, hogy sok függvénnyel terheli a globális névteret.

A másik megoldás a sok függvény problémára a nyelv prototípusosságában rejlik. JavaScriptben minden objektumban van egy rejtett hivatkozás egy másik objektumra, amit az objektum prototípusának nevezünk.

Az objektum1 prototípusa objektum2Az objektum1 prototípusa objektum2

Ennek a prototípus-objektumnak ugyancsak lehet prototípusa, majd annak is, stb., kialakítva így egy prototípus-láncolatot. Ha az objektum egy kulcsára hivatkozunk, akkor az értelmező először a megszólított objektumnál nézi meg, hogy a keresett kulcs megtalálható-e. Ha igen, visszaadja az alatta tárolt értéket. Ha nem, akkor megnézi a prototípus-objektumnál, és így tovább, végigvizsgálva a prototípus-láncolatot.

Egy bonyolultabb prototípus-láncolat sematikus ábrázolásaEgy bonyolultabb prototípus-láncolat sematikus ábrázolása

Ha tehát minden létrehozott objektumnak ugyanaz az objektum a prototípusa, és ebben vesszük fel a metódusokat, akkor a metódusfüggvények csak egyszer jönnek létre, mégis mindegyik objektum eléri őket a prototípus-láncolaton keresztül. Ezt a viselkedést úgy tudjuk elérni, hogy a konstruktorfüggvények prototype tulajdonsága alá vesszük fel a metódusokat. A new meghívásakor az újonnan létrejövő objektum prototípusa automatikusan a konstruktorfüggvény prototype tulajdonságára mutat.

Forráskód
function Gyerek(nev, kor) {
    this.nev = nev;
    this.kor = kor;
}
Gyerek.prototype.bemutatkozik = function () {
    console.log('A nevem: ' + this.nev);
};
Gyerek.prototype.alszik = function () {
    console.log('Zzzzzz...');
};
 
var david = new Gyerek('Dávid', 4);
var zsofi = new Gyerek('Zsófia', 7);
david.bemutatkozik();   //"A nevem: Dávid"
zsofi.bemutatkozik();   //"A nevem: Zsófia"
david, zsofi és a Gyerek.prototype objektumok viszonyadavid, zsofi és a Gyerek.prototype objektumok viszonya

Tulajdonságok újrahasznosításának egyik formája az öröklés, mely során a leszármazott objektum automatikusan megkapja a szülő objektum tulajdonságait. JavaScriptben ezt legegyszerűbben úgy érhetjük el, hogy a gyerek objektum prototípusában felveszünk egy szülő objektumot. Ha például óvodásokat szeretnénk létrehozni, akik gyerekek, de van jelük, és ezt el is tudják mondani, akkor az Ovodas függvényünknek a Gyerek függvényből kell származnia.

Forráskód
function Ovodas(nev, kor, jel) {
  this.base = Gyerek;
  this.base(nev, kor);
  this.jel = jel;
}
Ovodas.prototype = new Gyerek();
Ovodas.prototype.miAJeled = function () {
    console.log('A jelem: ' + this.jel);
}
 
var zsofi = new Gyerek('Zsófia', 7);
zsofi.bemutatkozik();   //"A nevem: Zsófia"
var david = new Ovodas('Dávid', 4, 'perec');
david.bemutatkozik();   //"A nevem: Dávid"
david.miAJeled();       //"A jelem: perec"

Ugyanezt a funkcionalitást elérhetjük konstruktorfüggvények nélkül is. Az ECMAScript 5-ös szabványa bevezetett egy Object.create() metódust, amellyel lehetővé válik egy új objektumnak egy másik objektumot prototípusának beállítani. Ennek részletes taglalása azonban nem fér e tananyag keretei közé.

Vissza a tartalomjegyzékhez

JavaScript beépített objektumai

A JavaScript nyelvbe számos előre beépített objektum van, amelyekkel gyakori feladatok elvégzése válhat könnyűvé.

Number

A Number objektum (igazából függvény) a számok csomagolóobjektuma. Általa a számokon meghívható néhány speciális formátumba alakító metódus:

Forráskód
//Számok mint objektumok metódusai
var a = 12.345;
a.toExponential();  //"1.2345e+1"
a.toExponential(2); //"1.23e+1"
a.toExponential(5); //"1.23450e+1"
a.toFixed();        //"12"
a.toFixed(2);       //"12.34"
a.toFixed(5);       //"12.34500"
a.toPrecision();    //"12.345"
a.toPrecision(2);   //"12"
a.toPrecision(5);   //"12.345"
 
a = 42;
a.toString();       //"42"
a.toString(2);      //"101010"
a.toString(5);      //"132"

A Number objektumnak önmagában is van pár hasznos tulajdonsága:

Forráskód
//A Number objektum tulajdonságai
Number.MAX_VALUE;           //A legnagyobb ábrázolható pozitív szám
Number.MIN_VALUE;           //A legkisebb ábrázolható negatív szám
Number.NaN;                 //NaN
Number.NEGATIVE_INFINITY;   //-Infinity
Number.POSITIVE_INFINITY;   //Infinity

String

A String objektum (ez is függvény) a szövegek csomagolóobjektuma, és jó pár hasznos metódust tesz elérhetővé a szövegpéldányokon. A teljesség igénye nélkül nézzünk néhány hasznos függvényt:

Forráskód
'piros alma'.charAt(2);                     //"r"
'piros alma'.charCodeAt(2);                 //114
'piros alma'.indexOf('alma');               //6
'piros alma'.localeCompare('piros körte');  //-1
'piros alma'.replace('piros', 'sárga');     //"sárga alma"
'piros alma'.substr(2, 3);                  //"ros"
'piros alma'.split(' ');                    //["piros","alma"]

Date

A Date objektumon keresztül különböző dátummal kapcsolatos funkcionalitás érhető el. Egy új időpontot létrehozni a new Date() utasítással lehet. Paraméter nélkül az aktuális időpontot adja vissza. Paraméterein keresztül adott időpont állítható be (new Date(év, hónap, nap[, óra, perc, másodperc, ezredmásodperc])). Műveletei három nagy csoportba tartoznak:

Forráskód
//Aktuális időpont lekérdezése
var most = new Date();
most.toLocaleString();      //"2013. július 31. 15:54:58"
most.getFullYear();         //2013
most.getMonth();            //6
most.getTime();             //1375279213631; 1970.01.01. óta eltelt ezredmásodpercek száma, a dátum belső ábrázolása
most.setFullYear(2011); 
most.toLocaleString();      //"2011. július 31. 15:54:58"
 
var maskor = new Date(2003, 7, 2);
maskor.toLocaleString();    //"2003. augusztus 2. 0:00:00"
 
most - maskor;              //252345871891; ezredmásodpercben

Math

A Math objektumon keresztül számos matematikai függvény érhető el. A teljesség igénye nélkül néhány példa:

A Math objektum jó néhány konstanst is rendelkezésünkre bocsát (csupa nagy betűsek):

Forráskód
Math.PI;                        //3.141592653589793
Math.sin(90 * Math.PI / 180);   //1; 90 fok szinusza
Math.random();                  //pl. 0.47057095554085615
Math.random();                  //pl. 0.5286946792885748
Math.round(1.6);                //2
Math.floor(1.6);                //1

Tömbműveletek

A tömbök is speciális objektumok, megannyi hasznos metódussal. Néhány fontosabb tömbfüggvény:

Forráskód
var t = [1, 2, 3, 4, 5];
t.push(6);      //6; tömb hosszát adja vissza;          tömb: [1, 2, 3, 4, 5, 6]
t.pop();        //6;                                    tömb: [1, 2, 3, 4, 5]
t.unshift(0);   //6; tömb hosszát adja vissza;          tömb: [0, 1, 2, 3, 4, 5]
t.shift();      //0;                                    tömb: [1, 2, 3, 4, 5]
t.reverse();    //[5, 4, 3, 2, 1];                      tömb: [5, 4, 3, 2, 1]
t.splice(2, 1); //[3]; kivágott elemeket adja vissza;   tömb: [5, 4, 2, 1]
t.join('###');  //"5###4###2###1"

Reguláris kifejezések

A reguláris kifejezések olyan minták, amelyek bizonyos karakterkombinációk szövegre illeszkedését vizsgálják. A minta az ábécé betűin túl speciális karaktereket használ az illeszkedés leírására.

Példa

Mielőtt a részletekbe belemennénk, nézzük meg a következő példát, amely azt vizsgálja, hogy egy adott szövegben szerepel-e valamilyen szám:

Forráskód
/\d+/.test('101 kiskutya');         //true
/\d+/.test('A halál 50 órája');     //true
/\d+/.test('Tíz kicsi néger');      //false

A sorok elején / jelek között található a minta, aminek illeszkedését a szövegre a test() metódussal nézzük meg. Mivel bármilyen számot nézni szeretnénk, így olyan szabályt kell megfogalmaznunk, ami tetszőleges számú számkaraktert néz egymás után. Egy tetszőleges számot a \d helyettesít, azt pedig a + jel írja le, hogy a számból 1 vagy több lehet egymás után.

Reguláris kifejezéseket leggyakrabban literálformával adunk meg. Ennek általános formája a következő:

Forráskód
/minta/módosítók

ahol a minta a „normális” karaktereken túl speciális karakterekből áll, a módosítók pedig az illesztés viselkedését szabályozó jelölők (karakterek). Az így létrehozott reguláris kifejezést vagy helyben felhasználjuk (ld. a fenti példát), vagy egy változóba eltároljuk:

Forráskód
var regkif = /\d+/;
regkif.test('A halál 50 órája');    //true

Néha előfordul, hogy reguláris kifejezések létrehozását a RegExp objektumon (függvényen) keresztül hozzuk létre. Erre akkor van szükség, ha a mintát dinamikusan (pl. szövegösszefűzéssel vagy felhasználói inputból) szeretnénk létrehozni. Ekkor a RegExp() függvénynek szöveges paraméterként adjuk meg a mintát és a módosítókat:

Forráskód
new RegExp('minta', 'módosítók');

A fenti példa ezzel így néz ki:

Forráskód
var regkif = new RegExp('\\d+');
regkif.test('A halál 50 órája');    //true

A minta legegyszerűbb esetben az ábécé karaktereiből áll. Ekkor azt nézzük meg, hogy a megadott szöveg (minta), szerepel-e egy az egyben a szövegben:

Forráskód
/nap/.test('Immár a nap leáldozott');   //true

A reguláris kifejezések erőssége azonban a speciális karakterek használatakor jön elő. Ezekkel ugyanis általánosabb illeszkedési szabályokat tudunk meghatározni. A teljesség igénye nélkül néhány gyakrabban előforduló speciális karakter a következő:

Ha speciális karaktert szeretnénk normális karakterként használni, akkor \ jelet kell elérakni.

Forráskód
/^Teremtő/.test('Teremtőnk kérünk tégedet');    //true
/velünk$/.test('Légy kegyes és maradj velünk'); //true
/,\s*/.test('Őrizzed, óvjad népedet!');         //true; van-e benne vessző és utána opcionális szóköz
 
//Van-e a szövegben ÉÉÉÉ. hónap NN. formátumban dátum?
/\d{4}\.\s\w+\s\d{1,2}\./.test('Ma 2013. augusztus 2.-a van.'); //true
/\d{4}\.\s\w+\s\d{1,2}\./.test('Kelt: Budapest, 2013.08.02.');  //false

Az illeszkedés módját a minta után megadott módosítók befolyásolják:

Forráskód
/^teremtő/.test('Teremtőnk kérünk tégedet');    //false
/^teremtő/i.test('Teremtőnk kérünk tégedet');   //true

A reguláris kifejezéseknek mint objektumoknak két saját metódusa van:

Forráskód
/m.g/g.test('Isten, áldd meg a magyart!');  //true
var t = /m.g/g.exec('Isten, áldd meg a magyart!');
t;          //["meg"]; az illeszkedő szövegrész
t.index;    //12; az illeszkedés helye
t.input;    //"Isten, áldd meg a magyart!"; az eredeti szöveg

A reguláris kifejezéseket intenzíven használják a különböző szövegmetódusok:

Forráskód
//Példa a cserére és a globális módosító használatára
"piros alma kukacos".replace(/os/, 'ított');    //"pirított alma kukacos"
"piros alma kukacos".replace(/os/g, 'ított');   //"pirított alma kukacított"
 
//Vezeték és keresztnév felcserélése
var re = /(\w+)\s(\w+)/i;
//vagy ha ékezeteket is támogatni szeretnénk
var re = /([A-ZÍÉÁŰŐÚÖÜÓ]+)\s([A-ZÍÉÁŰŐÚÖÜÓ]+)/i;
var sz = "Horváth Győző";
sz.replace(re, "$2, $1"); //Győző, Horváth
 
//Vesszővel elválasztott szavak felbontása
'alma, körte,szilva,      répa'.split(/,\s*/);  //["alma", "körte", "szilva", "répa"]

Bővebben a reguláris kifejezésekről a JavaScript referenciában és leírásban lehet olvasni.

Vissza a tartalomjegyzékhez

Időzítők

JavaScriptben lehetőség van egy függvény végrehajtását egy megadott idő eltelte utánra időzíteni. Alapvetően két függvény segítségével érhető ez el. A setTimeout() függvény egy függvény egyszeri végrehajtását végzi el a megadott idő elteltével. A setInterval() függvény viszont egy függvény adott időközönkénti ismételt végrehajtására szolgál. Mindkét függvénynél első paraméter a végrehajtandó függvény referenciája (vagy egy függvényliterál), második paraméterként pedig a késleltetés idejét kell megadni ezredmásodpercekben. Mindkét függvény egy időzítőazonosítóval tér vissza, amelyen keresztül meg lehet állítani az időzített végrehajtást. A setTimeout()-tal indított időzítőt a clearTimeout() függvénnyel lehet leállítani, a setInterval() párja a clearInterval(). Mindkét megállító függvénynek paraméterül az időzítőazonosítót kell megadni. Általános alakjuk tehát a következő:

Forráskód
//setTimeout és clearTimeout
var időzítőAzonosító = setTimeout(függvény, ms);
clearTimeout(időzítőAzonosító);
 
//setInterval és clearInterval
var időzítőAzonosító = setInterval(függvény, ms);
clearInterval(időzítőAzonosító);
Példa

Néhány példa:

Forráskód
//Meghívandó függvény definiálása
function csorog() {
    console.log('Brrrrrrr');
}
 
//setTimeout példa: óracsörgés 2 másodperc múlva
setTimeout(csorog, 2000);
 
//vagy egyben
setTimeout(function () {
    console.log('Brrrrrrr');
}, 2000);
 
//Időzítő leállítása még a csörgés előtt
var idozito = setTimeout(csorog, 2000);
clearTimeout(idozito);
 
//óra csörgése 2 másodpercenként
setInterval(csorog, 2000);
 
//ismételt csörgés leállítása
var idozito2 = setInterval(csorog, 2000);
clearInterval(idozito2);

Az időzítőket főleg hosszan tartó folyamatoknál használjuk. Azért van rájuk szükség, mert a JavaScript kód a böngészőben ugyanazon a programszálon fut, mint a felhasználói felület kezelése. Ez azt jelenti, hogy ha van egy 10 másodpercig futó kódunk (pl. prímszámkeresés), akkor a felület (azaz maga a böngésző) 10 másodpercig nem használható, nem reagál. Időzítők segítségével azonban lehetőség van ütemezni ezeknek a végrehajtását, időt adva a böngészőnek az egyéb felhasználói események végrehajtására is. Legelterjedtebb használata az animációknál volt (a CSS3 animációk megjelenése előtt).

Az időzítőkről bővebben például a Mozilla leírásában tudhatunk meg.

Vissza a tartalomjegyzékhez

Kivételkezelés

Egy alkalmazás írása közben számos hiba fordulhat elő. Egyrészt hibát jelezhet az értelmező a program futtatása során, másrészt mi magunk is jelezhetjük valamilyen módon, ha pl. egy függvény nem az előfeltételeknek megfelelő paramétereket kap, vagy nem a normális működést produkálja. Ebben az esetben megállapodhatunk, hogy speciális értékkel térünk vissza, pl. undefined-dal vagy null-lal, de a korszerűbb nyelvekben erre a megfelelő hiba dobása szolgál, a hívó programrészben pedig a keletkezett hibák elkapásával lehet a nem várt esetekre felkészülni. Ezt nevezzük kivételkezelésnek, amit a JavaScript nyelvi szinten is támogat.

A JavaScriptben számos előre beépített hibatípus létezik. Az általános Error objektumon kívül az alábbi hibaobjektumok fordulhatnak elő:

Mindegyik hibaobjektumnak két tulajdonsága van. A name a hiba típusát adja meg, míg a message a hiba leírását tartalmazza.

A kiváltott hibák kezelésére a try-catch-finally blokkok szolgálnak. A try blokkba kell írni a védendő kódot, amelyben a hiba előfordulását várjuk. Ha itt hiba keletkezik, akkor a blokk végrehajtása félbeszakad, és a vezérlés a catch blokknak adódik át, paraméterül megkapva a hibát reprezentáló kivételobjektumot. Itt kell kezelni a hibát. Végül finally blokkba írjuk azt a kódot, amit a try vagy catch blokkok után mindenféleképpen szeretnénk lefuttatni. A try blokkot vagy egy catch, vagy egy finally, vagy mindkettő követheti, így az alábbi lehetőségek fordulhatnak elő:

Forráskód
//Egy nem létező objektumra hivatkozva hiba lesz
try {
    alma.kukacos = true;
}
catch (e) {
    console.log(e.name);
    console.log(e.message);
}
finally {   //Akár el is hagyható
    console.log('Végem van...');
}
 
//Az eredménye:
//"ReferenceError"
//"alma is not defined"
//"Végem van...""

Kivételt akár mi is kiválthatunk a throw parancs segítségével. Dobhatunk egyrészt beépített hibaobjektumot az Error vagy valamelyik specifikusabb függvény segítségével, de hibaként generálhatunk saját hibaobjektumot is objektumliterál formájában, illetve objektumgenerátor vagy konstruktorfüggvény segítségével. Ebben az esetben a hibaobjektum bármilyen adattagokat tartalmazhat, de érdemes a natív hibaobjektumok alapján a name és a message mezőket megtartani.

Forráskód
//Beépített hiba dobása, pl. egy előfeltétel nem teljesülése esetén
if (typeof a !== 'number') {
    throw new Error('Nem szam a parameter!');
}
 
//Saját hiba dobása objektumliterál segítségével, pl. 0-val való osztásnál
if (oszto == 0) {
    throw {
        name: 'DivisionByZeroError',
        message: 'Az oszto nulla!'
    };
}
 
//Saját hiba dobása konstruktorfüggvénnyel
function DivisionByZeroError(message) {
    this.name = "DivisionByZeroError";
    this.message = message;
}
//...
if (oszto == 0) {
  throw new DivisionByZeroError('Az oszto nulla!');
}

A kivételkezelés további részletei a dokumentációban olvashatók:

• https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try…catch

• https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error

• https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Statements#Exception_Handling_Statements

Vissza a tartalomjegyzékhez

Új Széchenyi terv
A projekt az Európai Unió támogatásával, az Európai Szociális Alap társfinanszirozásával valósul meg.

A tananyag az ELTE - PPKE informatika tananyagfejlesztési projekt (TÁMOP-4.1.2.A/1-11/1-2011-0052) keretében valósult meg.
A tananyag elkészítéséhez az ELTESCORM keretrendszert használtuk.