Kihagyás

2. gyakorlat

WebStorm IDE használata

Új projekt létrehozása

  1. Nyisd meg a WebStormot.
  2. Kattints a "New Project" vagy "Create New Project" gombra.
  3. A felugró ablakban add meg a projekt helyét és nevét, és kattints a "Language" választónál a JavaScriptre. Amennyiben semmilyen feleslegesen generált dolgot nem szeretnél, válaszd az "Empty Project" opciót a bal oldali panelről. Ebben az esetben is állítsd be a projekt helyét és nevét.
  4. Kattints a "Create" gombra.

JavaScript fájlok létrehozása

  1. Jobb klikk a projekt mappájára a Project nézetben.
  2. Válaszd a "New" → "JavaScript File" opciót.
  3. Add meg a fájl nevét (.js kiterjesztés nélkül).
  4. Nyomj Entert.

JavaScript kód futtatása

  1. Jobb klikk a .js fájlra.
  2. Válaszd a "Run 'filename.js'" opciót.
  3. A kimenet a Run ablakban jelenik meg alul.

VAGY

  1. Kattints a zöld "Play" ikonra a WebStormban.
  2. A kimenet a Run ablakban jelenik meg alul.

Kommentek

JavaScriptben is lehetőségünk van kommentek (megjegyzések) írására.

Java, C nyelvekből ismerős lehet a szintaxis, amit használuk: az egysoros kommenteket // után adjuk meg, míg a több soros kommenteket /* és */ közé írjuk. A Pythonból ismerős # karaktert itt nem használhatjuk.

1
2
3
4
5
6
// this is a single-line comment

/*
    this is a
    multi-line comment
*/

Kiíratások

A gyakorlaton szinte mindig a console.log()-ot fogjuk használni kiíratásra. Ennek segítségével egyszerűen írhatunk adatokat a konzolra.

1
console.log("Hello!");

Fontosabb adattípusok

A JavaScript legalapvetőbb adattípusai: boolean, number, string és undefined.

A boolean (amint arra a nevéből rájöhetünk) logikai adattípus. Kétféle értéke lehet: true (logikai igaz érték) vagy false (logikai hamis érték).

A number adattípus a számok adattípusa lesz. JavaScriptben nincs külön egész és lebegőpontos típus, a szám adatok minden esetben number típusúak lesznek. Ez minden számot lebegőpontosként ábrázol, ami sajnos sok esetben pazarló.

A string természetesen a szöveges adattípust jelenti. JavaScriptben stringeket általában aposztrófok ('...') vagy idézőjelek ("...") között szoktunk megadni. A stringek összefűzése a + (plusz) operátorral történik.

1
2
3
4
console.log("apple" + "pie");
console.log("apple" + 'pie');
console.log('apple' + 'pie');
console.log('apple' + "pie");

A kimenet minden esetben applepie lesz.

A JavaScript egyik érdekes adattípusa az undefined, ami a definiálatlan értéket jelenti. Például amikor egy változót deklarálunk (létrehozunk), de nem adunk neki értéket, akkor a változó értéke automatikusan undefined lesz.

Típusellenőrzés

JavaScriptben a typeof operátor segítségével megkaphatjuk egy adott érték típusát. A visszaadott típus minden esetben egy szöveges érték lesz.

1
2
3
4
5
console.log(typeof 42);               // "number"
console.log(typeof 3.14);               // "number"
console.log(typeof "Cat");               // "string"
console.log(typeof "true");               // "string"
console.log(typeof true);               // "boolean"

Változók

Természetesen JavaScriptben is hozhatunk létre változókat, amelyeknek értéket a szokásos = operátorral adhatunk. JavaScriptben többféleképpen is létrehozhatunk változókat.

Tekintsük az alábbi két szintaxist:

  • var variableName = value;
  • let variableName = value;

Amint láthatjuk, változókat létrehozhatunk a nyelvben régebben óta létező var, illetve az újabb (ECMAScript 6 szabványban bevezetett) let kulcsszavakkal. Ahhoz, hogy megértsük a két kulcsszó közötti működésbeli különbséget, nézzük az alábbi kódpéldát!

1
2
3
4
5
6
7
{
    var a = 1;
    let b = 2;
}

console.log(a);
console.log(b);

Kimenet:

1
2
1
ReferenceError: b is not defined

Mi történt itt? Egy utasításblokkon (kapcsos zárójelpáron, de ez lehetne akár egy függvény törzse) belül létrehoztunk két változót: az a változót a var kulcsszóval, míg a b változót a let kulcsszóval.

Amikor a blokkon kívül kiírattuk a var kulcsszóval létrehozott változó értékét, akkor semmi gond nem volt, a blokkon belül létrehozott változó a blokkján kívül is látszott. Ez igen problémás lehet, hiszen ellentmond a többi programozási nyelv logikájának.

Ezzel szemben a let kulcsszóval létrehozott b változó a már jól megszokott módon viselkedik: az őt létrehozó blokkon belül lokális lesz, ha pedig ezen a blokkon kívül hivatkozunk rá, akkor hibaüzenetet kapunk.

Tipp

Összefoglalva: változók létrehozásakor használjuk inkább a let kulcsszót!

Az ECMAScript 6 szabvány a let mellett egy újabb módosítószót is hozott magával változók létrehozására, mégpedig a const kulcsszót, amit már a múlt órán láthattunk.

A const kulcsszóval létrehozott változók a let kulcsszóval létrehozott változókhoz hasonló módon viselkednek, azzal a kikötéssel, hogy az ő kezdőértéküket nem lehet módosítani ("konstans változók").

1
2
3
4
5
6
7
var a = 10;                    // do not use this
let b = 20;                    // use this instead
console.log("a value: " + a + ", b value: " + b);

const favoriteSubject = "Web programming";  // constant
// favoriteSubject = "Native Programming";        // TypeError: Assignment to constant variable.
console.log("My favorite subject is " + favoriteSubject);

Kimenet:

1
2
a value: 10, b value: 20
My favorite subject is Web programming

A változók létrehozása során a változónévre vonatkozóan van néhány tudnivaló, amivel érdemes tisztában lennünk:

  • A változónév nem kezdődhet számmal
  • A változónév betűt, számot és speciális jelet (_, $) tartalmazhat
  • Foglalt nevek nem használhatók változónévként (pl. function, return, let, class)

A JavaScript egy dinamikusan típusos nyelv, tehát lehetőségünk van arra, hogy ugyanabban a változóban eltérő típusú értékeket tároljunk.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let value;           // type of value: undefined
console.log(value);
console.log("type: " + typeof value);

value = 42;          // type of value: number
console.log(value);
console.log("type: " + typeof value);

value = "John";      // type of value: string
console.log(value);
console.log("type: " + typeof value);

Kimenet:

1
2
3
4
5
6
undefined
type: undefined
42
type: number
John
type: string

Típuskonverzió

JavaScriptben az adattípusok közötti konverzió automatikus. Két egyszerű példa automatikus típuskonverzióra:

  • Ha a + (plusz) operátor bármely operandusa szöveg, akkor az operátor stringösszefűzést fog végezni. Ekkor a nem string típusú operandusok automatikusan szöveges típusra lesznek konvertálva.
1
2
console.log("2" + 5 + 7);        // "2" + "5" + "7" = "257"
console.log(2.0 + "5" + 7.0);      // "2" + "5" + "7" = "257"
  • A * operátor a szorzást jelenti. Ha valamelyik operandusa nem szám típusú, akkor megpróbálja azt number típusúra konvertálni. Ha a konverzió sikeres, akkor elvégezzük a szorzást, ellenkező esetben pedig NaN-t kapunk vissza (Not a Number).
1
2
console.log("2" * 5);         // 2 * 5 = 10
console.log("cheese" * 5);    // NaN

NaN (Not a Number) JavaScriptben

Ahogy láttuk, egy szöveg összeszorzása egy számmal ebben a fenti esetben NaN értéket eredményezett. A NaN (Not a Number) egy speciális érték JavaScriptben, amely azt jelenti, hogy egy művelet eredménye nem értelmezhető számként. Bár a neve "Not a Number", technikai szempontból a NaN maga is number típusú érték.

1
2
console.log(typeof NaN); // "number"
console.log(NaN);        // NaN

Természetesen az automatikus típuskonverzió mellett lehetőségünk van manuálisan is egy adatot egy másikra típusra konvertálnunk bizonyos beépített függvények segítségével. Ezt nevezzük (explicit) typecasting-nak.

  • Boolean(expr): az expr kifejezést boolean típusúvá alakítja
  • Number(expr): az expr kifejezést number típusúvá alakítja
  • String(expr): az expr kifejezést string típusúvá alakítja
  • Számok közötti konverzióra használhatjuk a parseInt() és parseFloat() függvényeket
1
2
3
4
5
6
7
let a = Number("3.14");           // 3.14
let b = Number("101 dalmatians"); // NaN (Not a Number)
let c = parseInt(3.14);           // 3
let d = String(42);               // "42"

// number -> boolean konverzió esetén: 0 -> false, minden más -> true
let e = Boolean(0);               // false

Fontosabb operátorok

A JavaScript fontosabb operátorai:

Kategória Operátorok
Aritmetikai operátorok +, -, *, /, %, **
Hozzárendelő operátorok =, +=, -=, *=, /=
Incrementáló, decrementáló operátorok ++, --
Összehasonlító operátorok ==, ===, !=, !==, <, <=, >, >=
Logikai operátorok &&, ||, !

A legtöbb operátor a korábban tanultakkal megegyező módon viselkedik (hasonlóan, mint Pythonban vagy éppen mint Javaban).

  • A / operátor mindig (egész operandusok esetén is) lebegőpontos osztást végez
  • Hatványozásra a ** (dupla csillag) operátor alkalmas
  • JavaScriptben használhatjuk a ++ és -- operátorokat egy változó értékének 1-gyel való növeléséhez vagy csökkentéséhez

Érdekesek még az == (dupla egyenlő) és az === (tripla egyenlő) operátorok. Mindkettőt összehasonlításra használjuk, viszont van egy lényegi különbség a két operátor működésében:

  • Az == pontosan akkor ad vissza igazat, ha a két operandusának értéke megegyezik
  • Az === pontosan akkor ad vissza igazat, ha a két operandusának értéke és típusa egyaránt megegyezik
1
console.log(typeof 42 === "number"); // true

Példa: Az == és === operátorok működésbeli különbsége

1
2
console.log(42 == "42");
console.log(42 === "42");

Kimenet:

1
2
true
false

Mi is történik itt? Mivel egy számot akarunk egy stringgel összehasonlítani, ezért a JavaScript automatikus típuskonverziót végez. A konverzió után a két változó értéke megegyezik (42), így az == operátor igazat ad vissza. Viszont mivel a 42 egy number, míg a "42" egy string típusú adat, ezért az === operátor visszatérési értéke hamis lesz.

Tipp

Az összehasonlításoknál általában érdemes típusra is ellenőriznünk, tehát használjuk az === operátort!

Az == operátor tagadása a != (ez pontosan akkor ad vissza igazat, ha a két operandus eltérő értékű), míg az === operátort a !== segítségével tagadhatjuk (ez pontosan akkor ad vissza igazat, ha a két operandus eltérő értékű vagy eltérő típusú).

Típuskonverzió unáris operátorokkal

A + operátor JavaScriptben kétféle funkciót is ellát: működhet unáris operátorként (típuskonverzióra) és bináris operátorként (összeadásra vagy string összefűzésre). Ez a kettős szerep gyakran zavart okozhat. Amikor a + operátort egyetlen operandussal használjuk (unáris operátor), akkor az operandust number típusúra próbálja konvertálni. Ez egy gyors módja a típuskonverziónak.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// String -> number conversion
console.log(+"5");          // 5
console.log(+"3.14");       // 3.14
console.log(+"-42");        // -42
console.log(+"0");          // 0

// Boolean -> number conversion
console.log(+true);         // 1
console.log(+false);        // 0

// Special cases
console.log(+"");           // 0 (empty string)
console.log(+" ");          // 0 (whitespace)
console.log(+null);         // 0
console.log(+undefined);    // NaN

Hasonlóképp, ez a - operátorral is működhet, bár ezt ritkábban láthatni valós kódban.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// String -> number conversion
console.log(-"5");          // -5
console.log(-"3.14");       // -3.14
console.log(-"-42");        // 42
console.log(-"0");          // -0

// Boolean -- number conversion
console.log(-true);         // -1
console.log(-false);        // -0

// Special cases
console.log(-"");           // -0 (empty string)
console.log(-" ");          // -0 (whitespace)
console.log(-null);         // -0
console.log(-undefined);    // NaN

Érvénytelen konverziókat is végezhetünk, ezek eredménye azonban nem mindig egyértelmű, néhány példa:

1
2
3
4
5
6
console.log(+"hello");      // NaN
console.log(+"123abc");     // NaN
console.log(+"abc123");     // NaN
console.log(+{});           // NaN
console.log(+[]);           // 0 (empty array)
console.log(+[1,2,3]);      // NaN (array with multiple elements)

Az operátort használhatjuk bármilyen művelet során:

1
2
3
4
5
let x = "10";
let y = "20";

console.log(+x + +y);       // 30
console.log(Number(x) + Number(y));  // 30

Célszerű körültekintően használni ezt a fajta konverziós operátort, mert az ember könnyen írhat olyan kódot, amiről nem tudja, hogy pontosan milyen végeredményt ad.

Az alább láthatunk két példát. Az első esetben az operátorok precedenciája miatt először elvégzésre kerül az összeadás, majd pedig a szöveggé alakítás és összefűzés, a másik esetben pedig mivel egy szöveg van a művelet elején, így minden további "összeadás" szöveg összefűzést fog jelenteni.

1
2
3
4
5
6
7
let result = 1 + 2 + "3";
console.log(result);        // "33" (not "123")
// evaluation left to right: (1 + 2) + "3" = 3 + "3" = "33"

let result2 = "3" + 1 + 2;
console.log(result2);       // "312"
// evaluation left to right: ("3" + 1) + 2 = "31" + 2 = "312"

Csak a + operátor használatával elég cifra kifejezéseket is készíthetünk.

1
2
console.log(+"5" + +"3");   // 8 (unary + first, then addition)
console.log(+("5" + "3"));  // 53 (string concatenation first, then conversion)

Pontosvessző használata JavaScriptben

A JavaScriptben pontosvesszőket (;) használunk az utasítások lezárására. Bár a JavaScript rendelkezik Automatikus Pontosvessző Beszúrás (ASI) funkcióval (bővebben), ami azt jelenti, hogy a pontosvesszők technikailag opcionálisak sok esetben, bevált gyakorlat, hogy mindig használjuk őket, ezt több style guide is ajánlja. Sőt, ez segít a kódot egyértelműbbé és könnyebben olvashatóvá tenni.

Ezen felül azonban előfordulhat, hogy az ASI-ra támaszkodás hibás működést eredményez. Tekintsük az alábbi példát.

1
2
3
4
5
6
function calculateCircleArea(radiusOfTheCircle) {
    return
    3.141592653589793238462643383279502884197 * radiusOfTheCircle * radiusOfTheCircle
}

console.log(calculateCircleArea(10)); // undefined

A console.log által kiírt érték az elvárthoz képest egészen más, egészen pontosan undefined. Ennek oka az ASI, ami a return után gondolta úgy, hogy oda kellene amúgy a pontosvessző, így oda illesztette be.

Jelenleg a legegyszerűbb megoldás, ha nem törjük meg a sort, azonban a későbbiekben még látni fogunk példát helytelen ASI-ra.

1
2
3
4
5
function calculateCircleArea(radiusOfTheCircle) {
    return 3.141592653589793238462643383279502884197 * radiusOfTheCircle * radiusOfTheCircle;
}

console.log(calculateCircleArea(10)); // 314.1592653589793

Mindig zárd le az utasításaidat pontosvesszővel! Ez megelőzi a lehetséges problémákat és kiszámíthatóbbá teszi a kódot.

Feladatok

1. feladat: Kézfogás (2 pont)

Egy több tagú baráti társaságban mindenki mindenkivel kezet fog (nyilván önmagával senki sem fog kezet, ennyire kétségbeesettek azért nem vagyunk). Írj egy kezfogas nevű függvényt, amely a társaságban lévő emberek számát kapja paraméterül, és visszaadja, hogy összesen hány kézfogás történt!

Példa:

  • Input: 10
  • Return: 45

2. feladat: Egyezés (2 pont)

Írj egy egyezes nevű függvényt, amely két tetszőleges típusú paramétert vár! A függvény adja vissza, hogy a két paraméter értékre és típusra is megyezik-e!

Példa:

  • Input: 1, true
  • Return: false

Példa:

  • Input: false, false
  • Return: true

3. feladat: Furcsa matematika (2 pont)

Mit írnak ki az alábbi kifejezések? Először gondold végig, majd ellenőrizd őket az IDE-ben.

1
2
3
4
5
6
console.log("2" + 3 + 4);
console.log(2 + 3 + "4");
console.log("10" - 5);
console.log("10" * "2");
console.log("apple" / 2);
console.log(+"42" + 8);

4. feladat: Átlagszámítás

Írj egy atlag függvényt, amely három számot kap paraméterül és visszaadja a számtani közepüket!

1
2
3
4
5
6
function atlag(a, b, c) {
    // Itt a kódod
}

console.log(atlag(10, 20, 30)); // 20
console.log(atlag(5, 7, 9));    // 7

5. feladat: Parkolás

Egy parkolóban az első óra 300 Ft, minden további megkezdett óra 200 Ft. Írj egy parkolodij függvényt, amely a parkolási időt órában kapja paraméterül, és visszaadja a fizetendő összeget!

1
2
3
4
5
6
7
8
9
function parkolodij(orak) {
    // Itt a kódod
}

console.log(parkolodij(1));   // 300
console.log(parkolodij(2));   // 500  

// Nézz utána, hogy kellene ezt megoldani
console.log(parkolodij(3.5)); // 700 (4 órát fizet)