Kihagyás

10. gyakorlat

A gyakorlat anyaga

Ezen a gyakorlaton megismerkedünk a JavaScript fontosabb adatszerkezeteivel.

Tömbök

JavaScriptben a tömb (Array) tetszőleges mennyiségű, nem feltétlenül azonos típusú adat tárolására alkalmas adatszerkezet.

Tömb létrehozása

JavaScriptben alapvetően kétféle módszerrel hozhatunk létre tömböket:

  • a new Array() segítségével
  • a tömbelemek szögletes zárójelek közötti felsorolásával.

A későbbiekben szinte mindig a tömbelemek szögletes zárójelek közötti felsorolását fogjuk használni tömbök létrehozásakor.

Példa: Tömb létrehozása

1
2
3
4
5
let tomb1 = new Array(10);      // egy 10 elem tárolósára képes tömb létrehozása (üres értékek)
let tomb2 = new Array(10, 20);  // egy, a 10 és 20 elemeket tároló tömb létrehozása

let tomb3 = [];                 // üres tömb létrehozása
let tomb4 = [10, 20, 30, 40];   // szám adatokat tároló tömb létrehozása

Tömb hosszának a lekérdezése

Egy tömb hosszának lekérdezésére a length property-t használjuk JavaScriptben.

1
2
let gyumolcsok = ["alma", "körte", "szilva", "barack"];
console.log(gyumolcsok.length);

Kimenet

4

Tömbelemek indexelése

A tömbök elemeit a szokásos tömbindex operátorokkal tudjuk elérni: tombNeve[index].

Az indexelés itt is 0-tól kezdődik. A Pythonban tanult negatív, illetve intervallumos indexelés JavaScriptben nem működik!

Ha JavaScriptben egy nem létező indexű tömbelemre hivatkozunk (pl. alul- vagy túlindexeljük a tömböt), akkor undefined értéket kapunk.

1
2
3
4
5
let macskak = ["Garfield", "Nermal", "Grumpy Cat", "Tom"];

console.log(macskak[0]);                        // a legelső elem
console.log(macskak[macskak.length - 1]);       // az utolsó elem
console.log(macskak[-1]);                       // ez JavaScriptben nem működik!

Kimenet

Garfield Tom undefined

A stringekkel ellentétben a lista egy mutable (módosítható) típus, így lehetőségünk van arra, hogy egy adott indexű elem értékét módosítsuk.

1
2
3
let macskak = ["Garfield", "Nermal", "Grumpy Cat", "Tom"];
macskak[1] = "Szilveszter";
console.log(macskak);

Kimenet

[ 'Garfield', 'Szilveszter', 'Grumpy Cat', 'Tom' ]

Tömbök bejárása

Ha végig szeretnénk iterálni egy tömb elemein, akkor azt egy for ciklussal tudjuk egyszerűen megtenni. Kétféle szintaxist használhatunk:

  • a hagyományos, index alapján történő bejárást
  • listaszerű bejárást (for-of szintaxis).

Példa: Tömb elemeinek bejárása

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
let macskak = ["Garfield", "Nermal", "Grumpy Cat", "Tom"];

// hagyományos, index alapú bejárás

for (let i = 0; i < macskak.length; i++) {
    console.log(macskak[i]);
}

console.log("----------------------------");

// listaszerű bejárás - a 'macska' változó rendre felveszi a tömbelemek értékét

for (let macska of macskak) {
    console.log(macska);
}

Tömbkezelő függvények

A JavaScript számos beépített függvényt biztosít tömbök kezelésére. Ezek közül néhány hasznosabb:

  • t.pop() törli (és visszaadja) az utolsó elemet a t tömbből
  • t.push(a, b, ...): beszúrja az a, b, ... elemeket a t tömb végére
  • t.shift(): törli (és visszaadja) a legelső elemet a t tömbből
  • t.unshift(a, b, ...): beszúrja az a, b, ... elemeket a t tömb elejére
  • t.sort(): rendezi a t tömb elemeit
  • t.indexOf(e): visszaadja az e elem legelső előfordulásának a kezdőindexét a t tömbön belül (-1-et ad vissza, ha nem szerepel benne)
  • t.slice(startIndex, endIndex): visszaadja a tömb startIndex és endIndex közötti elemeit
    • mindig egy új tömböt ad vissza (nem módosítja az eredeti tömböt)
    • az endIndex indexű elem már nem lesz benne a visszaadott tömbben
    • az endIndex paraméter elhagyható: ha nem adjuk meg, akkor startIndex-től kezdve a tömb összes "hátralévő" elemét kapjuk vissza
  • t.join(separator): egy stringgé konvertálja a tömböt, amiben a tömbelemek separator karakterrel lesznek elválasztva
  • ...

Példa: Tömbkezelő függvények használata

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
let bevasarlolista = ["tej", "tojás", "sajt", "üdítő"];

bevasarlolista.pop();                           // törlés a végéről
bevasarlolista.push("kenyér", "felvágott");     // beszúrás a végére
bevasarlolista.shift();                         // törlés az elejéről
bevasarlolista.unshift("kalkulus példatár");    // beszúrás az elejére

bevasarlolista.sort();                          // rendezés
let szovegkent = bevasarlolista.join("; ");     // szövegként reprezentálás
console.log("Ezeket kell megvennünk: " + szovegkent);

let fontos = bevasarlolista.slice(1, 3);        // "résztömb" lekérése
console.log("Minél hamarabb vegyük meg:");
console.log(fontos);

Kimenet

Ezeket kell megvennünk: felvágott; kalkulus példatár; kenyér; sajt; tojás Minél hamarabb vegyük meg: [ 'kalkulus példatár', 'kenyér' ]

Az object adattípus

A JavaScript egyik beépített adattípusa az object (objektum). Ennek segítségével komplex entitásokat tudunk létrehozni, amelyekbe property-érték párokat helyezhetünk.

Object létrehozása

JavaScriptben objektumokat kétféleképpen hozhatunk létre:

  • a new Object() konstruktor használatával
  • a kapcsos zárójel ({}) operátorok segítségével.

Példa: Üres object-ek létrehozása

1
2
let ures1 = new Object();
let ures2 = {};

A továbbiakban a kapcsos zárójeles szintaxist fogjuk használni a jegyzetben. A kapcsos zárójel között, vesszővel elválasztva megadhatjuk az adott objektum property-érték párjait property: érték formában.

Példa: Egy személy object létrehozása

1
2
3
4
5
6
let szemely = {
    nev: "Béla",
    eletkor: 30,
    foglalkozas: "programozó",
    hazas: false
};

Object elemeinek elérése

Egy object adott property-jéhez tartozó értéke kétféleképpen is lekérdezhető:

  • a . (pont) operátorral
  • a [] (szögletes zárójel) operátorral.

Példa: A nev property-hez tartozó érték lekérése

1
2
3
4
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };

console.log(szemely.nev);       // . operátor
console.log(szemely["nev"]);    // [] operátor

Kimenet

Béla Béla

A lényegi különbség a két operátor működésében, hogy amennyiben változót adunk át nekik, akkor a . operátor a változó nevét tekinti kulcsnak, míg a [] operátor a változó értékét fogja kulcsként venni.

Példa: A . és [] operátorok közötti működésbeli különbség

1
2
3
4
5
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };
let valami = "eletkor";

console.log(szemely.valami);
console.log(szemely[valami]);

Kimenet

undefined 30

A példában az első esetben a . operátor egy valami nevű property-t keresett az objektumon belül, amit nem talált meg, így undefined értéket kaptunk. A második esetben a [] operátor, már a valami változóban szerepelő értéket, az eletkor property-t kereste, és mivel van ilyen property-nk az objektumunkban, ezért az ahhoz tartozó értéket kaptuk vissza.

Fontosabb object műveletek

Property előfordulásának ellenőrzése

Az előző példában láttuk, hogy amennyiben az object egy nem létező property-jének az értékét szeretnénk lekérni, undefined értéket kapunk. Ezt kihasználva könnyedén tudjuk ellenőrizni, hogy egy adott property szerepel-e az object-ben.

1
2
3
4
5
6
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };

if (szemely.foglalkozas !== undefined) {
    console.log("Van foglalkozas nevű property-nk!");
    console.log("Értéke: " + szemely.foglalkozas);
}

Kimenet

Van foglalkozas nevű property-nk! Értéke: programozó

A fenti módszerrel viszont van egy probléma: mi van akkor, ha a foglalkozas property értékét undefined-ra állítjuk be? Ekkor az if-ben megadott feltétel nem fog teljesülni, és hibásan úgy vesszük, mintha nem szerepelne ilyen nevű property az object-ben. Emiatt célszerű inkább használni az in operátort.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: undefined };

if (szemely.foglalkozas !== undefined) {
    // ebbe az if-be nem lépünk bele...
    console.log("Van foglalkozas nevű property-nk!");
}

if ("foglalkozas" in szemely) {
    console.log("Van foglalkozas nevű property-nk!");
}

Kimenet

Van foglalkozas nevű property-nk!

Érték módosítása

Az object egy adott property-jéhez tartozó értékét módosíthatjuk is. Hivatkozunk a módosítani kívánt elemre (a fentebb tárgyalt . vagy [] operátorok valamelyikével), majd az = operátorral beállítjuk az új értéket.

1
2
3
4
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };
szemely.foglalkozas = "asztronauta";  // szemely["foglalkozas"] = "asztronauta" is helyes

console.log(szemely.nev + " munkát váltott, mától " + szemely.foglalkozas + "!");

Kimenet

Béla munkát váltott, mától asztronauta!

Új property-érték pár beszúrása

Az objektumainkba bármikor beszúrhatunk új property-érték párokat. A beszúrás szintaxisa nagyon egyszerű: megadjuk az object beszúrni kívánt property-jének a nevét, majd = operátorral értéket adunk neki.

1
2
3
4
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };
szemely.kedvencSzin = "átlátszó";

console.log(szemely);

Kimenet

{ nev: 'Béla', eletkor: 30, foglalkozas: 'programozó', kedvencSzin: 'átlátszó' }

Property-érték pár törlése

A delete kulcsszóval lehetőségünk van egy adott property-t és a hozzá tartozó értéket törölni az object-ből.

1
2
3
4
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };
delete szemely.foglalkozas;

console.log(szemely);

Kimenet

{ nev: 'Béla', eletkor: 30 }

Object-ek bejárása

Az object-ek property-érték párjának bejárása legegyszerűbben egy for-ciklussal tehető meg. Az alábbi három módszer mindegyike ezt valósítja meg (amelyik a 3 közül a legszimpatikusabb a számunkra, azt használjuk).

  • for-in szerkezet:
1
2
3
4
5
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };

for (let kulcs in szemely) {
    console.log(kulcs + " értéke: " + szemely[kulcs]);
}
  • for-of szerkezet, az Object.keys() használatával:
1
2
3
4
5
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };

for (let kulcs of Object.keys(szemely)) {
    console.log(kulcs + " értéke: " + szemely[kulcs]);
}
  • for-of szerkezet, az Object.entries() használatával:
1
2
3
4
5
let szemely = { nev: "Béla", eletkor: 30, foglalkozas: "programozó" };

for (let [kulcs, ertek] of Object.entries(szemely)) {
    console.log(kulcs + " értéke: " + ertek);
}

Figyelem

Ha böngészős környezetben lennénk, akkor érdemes tudnunk, hogy a harmadik, Object.entries() használatával történő megvalósítást az Internet Explorer nem támogatja natív módon.

Úton az objektumorientált paradigma felé

Az object egy hasznos, viszonylag gyakran használt adatszerkezet JavaScriptben. Ennek ellenére van némi probléma vele, amit érdemes megjegyezni.

Ha az objektumunkban van egy függvény, és az objektum bejárása során azt meg szeretnénk hívni, akkor ez egy kissé körülményes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
let szemely = {
    nev: "Béla",
    eletkor: 30,
    bemutatkozik: function() {
        // az objektumon belül a property-ket a this kulcsszóval érhetjük el
        console.log("Szia! " + this.nev + " vagyok, " + this.eletkor + " éves.");
    }
};

for (let [kulcs, ertek] of Object.entries(szemely)) {
    if (typeof ertek === "function") {  // ha a property-hez tartozó érték függvény, hívjuk meg
        // ertek();             // nem jó! (az adattagok értéke undefined lesz)
        ertek.apply(szemely);   // így már jó lesz
    }
}

Kimenet

Szia! Béla vagyok, 30 éves.

Emellett, ha nem 1 személyünk lenne, hanem mondjuk 100, akkor 100 különböző személy object-et kellene kézzel létrehoznunk, amelyekben külön-külön megadnánk a property-érték párokat.

Ezt persze nem szeretnénk manuálisan elvégezni, így felmerül az igény arra, hogy hozzunk létre egy "blueprint"-et, ami megmondja, hogy hogyan fognak kinézni az objektumaink. Ez a "blueprint" lesz a más nyelvekből ismerős osztály. Ha van egy Szemely osztályunk, abból már egyszerűen tudunk személy objektumokat készíteni a példányosítás során.

Az osztályokról, illetve az objektumorientáltság JavaScriptben való megvalósításáról a következő gyakorlaton fogunk tanulni.

Kiegészítés: Egyéb adatszerkezetek

Noha a gyakorlaton főként tömbökkel és object-ekkel foglalkozunk, ezeken kívül további hasznos adatszerkezetek is léteznek JavaScriptben.

A map (leképezés) kulcs-érték párok tárolására alkalmas adatszerkezet, így funkcióját tekintve valamelyest hasonlít az object-re. A linkre kattintva olvashatunk az leképezés és az object főbb különbségeiről is.

A set (halmaz) olyan adatszerkezet, amelyben nem lehetnek duplikátumok, és az elemek között nincs sorrendiség. Fontosabb metódusaira példát a linkre kattintva láthatunk.

Ez a két adatszerkezet az előadáson kerül tárgyalásra.

Feladatok

Az anyagrészhez tartozó gyakorló feladatsor elérhető itt.


Utolsó frissítés: 2020-11-18 08:38:30