Webprogramozás

Követelmények, JavaScript nyelvi elemek

Horváth Győző
Egyetemi docens
1117 Budapest, Pázmány Péter sétány 1/c., 2.408-as szoba
Tel: (1) 372-2500/8469
horvath.gyozo@inf.elte.hu

Dinamikus webprogramozás

Statikus vs dinamikus

Eddigi ismeretek

  • Statikus weblapok készítése
  • Webfejlesztés
    • HTML5
    • CSS 1, 2, 3
    • Alapvető HTTP ismeretek
    • CSS keretrendszerek (Bootstrap)

Kliens-szerver architektúra

  • Web: kliens és kiszolgáló kommunikációja
  • HTTP: a kommunikáció protokollja
  • Kliens kérést intéz a szervernek
  • Szerver válaszol
  • A kliens feldolgozza a választ

Statikus oldalak

  • Szerver szempontjából statikus
    • Kérés pillanatában a szerveren megtalálható az a tartalom, amely leküldésre kerül a válaszban
    • Fájlkiszolgálás
  • Kliens szempontjából statikus
    • A letöltött és a létrejött tartalom az oldal élettartamának a végéig ugyanaz
    • Nem változik meg sem a böngésző állapota, sem a betöltött dokumentum szerkezete
    • Nem fut le benne programkód, leíró nyelv, deklaratív

Dinamikus oldalak

  • Szerver szempontjából dinamikus
    • A válaszként leküldött tartalmat program állítja elő
    • A kérés pillanatában a válasz még nem létezik a szerveren
  • Kliens szempontjából dinamikus
    • A letöltött tartalomban programkód fut le
    • Ez megváltoztathatja a böngésző állapotát és a dokumentum szerkezetét
  • → programozás

Miről lesz szó?

  • Dinamikus weblapkészítés
  • Dinamikus webprogramozás
  • Kliens-szerver architektúra mindkét oldalán
    • Kliensoldalon: JavaScript
    • Szerveroldalon: PHP
  • Alapvető ismeretek, bevezetés
    • Új nyelvek
    • Új technológiák
    • Új programozási modellek

Félév felépítése

  • Első felében a kliens oldali dinamikus webprogramozás alapjaival ismerkedünk meg
    • JavaScript
  • Második felében a szerver oldali dinamikus webprogramozás alapjai következnek
    • PHP

Motiváció

Trendek

  • Desktop → Web
  • Natív mobil
  • Web → Mobil
  • Web → Desktop
  • IOT, robotika

Cél

  • Összetettebb alkalmazás készítése
  • Játék
    • kliensoldal
    • szerveroldal

Követelmények

Tárgy honlapja

http://webprogramozas.inf.elte.hu/#!/subjects/webprog-pti

Általános információk

  • Óraszám: 1 előadás + 2 gyakorlat + 1 konzultáció
  • Előfeltétel: Webfejlesztés
  • Számonkérés: folyamatos számonkérésű tárgy

Követelmények

  • Előadás kötelező
  • Gyakorlatok kötelező
    • Legfeljebb 3 hiányzás
  • Két beadandó
    • JavaScript
    • PHP
  • Évfolyam zh
    • PHP és JavaScript

Követelmények

  • Beadandó
    • Értékelés: -0,5; 0; 0,5
  • Évfolyam zh
    • 1-től 5-ig
  • Plágiumellenőrzés
    • másolás esetén nincs jegy

Követelmények

  • Jegyszerzés feltételei
    • Részvétel a gyakorlatok legalább 75%-án (maximum 3 hiányzás)
    • Két elfogadott beadandó
    • Megírt évfolyam zh
  • Értékelés
    • Évfolyam zh + JS beadandó + PHP beadandó
    • A 2-es érdemjegyhez legalább 2-esre megírt évfolyam zh szükséges.

Határidők

  • JavaScript beadandó
    • 2019. október vége, november eleje
  • PHP beadandó
    • 2019. december közepe
  • Évfolyam zh
    • 2020. január 7. kedd, 9-12, Lovarda, Nyelvi és Adatbázis labor
    • 2020. január 7. kedd, 13-16, Lovarda, Nyelvi és Adatbázis labor
  • Pótzh
    • 2020. január 14. kedd, 9-12, Lovarda és Nyelvi labor

Kliensoldali webprogramozás

JavaScript története

A kezdet

  • 1991: világháló születése
  • 1993: első grafikus böngészők
  • 1994: Netscape Navigator böngésző
  • 1995 áprilisa: Netscape cég → Brendan Eich: olyan programozási nyelv, amelyekkel interaktívvá tehetők weboldalak
  • Cél: Java pluginek elérése nem Javás programozóknak
  • 1995 decembere: bejelentik a JavaScriptet

Név és szabvány

  • Elnevezések
    • LiveScript
    • JavaScript: marketing miatt a Java programozók átcsábítására (web Visual Basic-je)
  • Szabvány: ECMAScript
    • Európai Informatikai és Kommunikációs Rendszerek Szabványosítási Szövetsége (ECMA)
  • Microsoft
    • JScript

Történet

  • 1996-1999: I. böngészőháború
    • Netscape Navigator vs. Microsoft Internet Explorer
    • → kliensoldal megbízhatatlan
  • 1999: Sötét középkor
    • Szerveroldali technológiák fejlődése
  • 2000-2007: II. böngészőháború (alternatív böngészők)
  • 2006: JavaScript újrafelfedezése (AJAX, jQuery)
  • 2008: Google Chrome
  • 2008-: III. böngészőháború (JS sebessége)
  • 2009: parancssori JavaScript

ECMAScript verziók

  • 1997: 1. verzió
  • 1999: 3. verzió
  • 2009: 5. verzió (ES5)
    • hibajavítás
    • apróbb fejlesztések
  • 2015: 6. verzió (ES6, ECMAScript 2015)
    • nagyobb fejlesztések
    • modern nyelvi tulajdonságok
  • 2016: 7. verzió (ES7, ECMAScript 2016)
  • 2017: 8. verzió (ES8, ECMAScript 2017)
  • Stages: 0, 1, 2, 3, 4 → szabvány

Fejlesztőeszközök

Szerkesztők, böngészők, eszköztárak, dokumentáció

Szerkesztők

  • Tetszőleges modern kódszerkesztő használható
  • Text editorok
    • Notepad++
    • Sublime Text 3
    • Atom
    • Visual Studio Code
  • Integrált fejlesztőkörnyezetek
    • Netbeans IDE
    • Visual Studio
    • Webstorm

Böngészők

  • Google Chrome
  • Mozilla Firefox
  • Edge
  • Safari
  • Opera

Webfejlesztési eszközök

  • Webfejlesztő eszköztár (F12)
    • Elemek
    • JavaScript konzol (console)
    • Debugger
    • Erőforrások
    • Hálózati forgalom
    • Teljesítményprofilozás
  • Parancssori eszközök

Dokumentáció

Futtató környezet

Futási környezet

A JavaScriptnek szüksége van egy futtató környezetre

  • Böngésző
  • Parancssor (node.js)

Hova írhatjuk a kódot?

  • JavaScript konzolba (böngésző)
    • Az adott oldal kontextusában értelmezésre kerül
    • Kipróbálásra jó
  • HTML kódba (böngésző)
    • Inline szkript, <script> tag, bárhova rakhatjuk
    • Külső állományba, <script> tag src attribútumával töltjük be
  • Parancssori értelmezőbe (parancssor, Node.js)

JavaScript kód helye

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Webfejlesztés 2.</title>
    <script>
      //JavaScript kód helye
    </script>
    <script src="jskod.js"></script>
  </head>
  <body>
    <script>
      //JavaScript kód helye
    </script>
    <p>Hello világ!</p>
    <script src="jskod2.js"></script>
  </body>
</html>

JavaScript kód helye

<!doctype html>
<html>
  <head>
    <!-- ... -->
  </head>
  <body>
    <!-- ... -->
    <script src="kod.js"></script>
  </body>
</html>

A JavaScript nyelv

Alapok

Mintaként szolgáló nyelvek

#include <iostream>
using namespace std; 
int main() { 
  //declaration 
  const int n=5; 
  double x[]={1,3,5,7,9}; 
  double s; 
  //process
  s=0; 
  for(int i=0; i<n; i++) { 
    s=s+x[i]; 
  } 
  //write output
  cout<<"Sum: "<<s<<endl; 
  return 0; 
} 
//declaration 
const x=[1,3,5,7,9];
let s;
//process 
s=0;
for(let i=0; i<x.length; i++) {
    s=s+x[i];
}
//write output 
console.log('Sum: ', s);

C++

  • Erősen típusos
  • Fordított
  • Általános célú programozási nyelv

JavaScript

  • Dinamikusan típusos
  • Interpretált
  • Szkriptnyelv

Dinamikusan típusos

  • Dinamikusan tipizált nyelv
  • A változók típusa a benne tárolt érték típusától függ
  • Vagy másképp: a típusok az értékekhez tartoznak, nem a változókhoz.
  • Automatikus típuskonverziók (lehetőleg kerüljük)
a = 'alma';
a = 12;
a == '12'; //true

Interpretált

  • A böngészőben futó értelmező értelmezi a JavaScript kódsorokat sorról sorra
  • Nincs fordítási fázis, nem a lefordított kód fut
  • Minimális előfeldolgozás történik
  • A kód a hibáig lefut, ott elakad
    • Az adott <script> blokk futása megáll
    • A <script> blokk után folytatódik az oldal betöltése

További jellemzők

  • Kis és nagybetűk különböznek
  • Nincs főprogram (main)
  • Nincs input/output
  • Nincs fájlkezelés
  • Objektumorientált
  • Prototípusos
  • Automatikus pontosvessző beszúrás
let a = 12  // --> let a = 12;
a = a + 1   // --> a = a + 1;

Típusok

  • Egyszerű típusok
    • Szám
    • Szöveg
    • Logikai
    • null
    • undefined
  • Összetett típusok
    • Tömb
    • Objektum
    • Függvény

Literálformák

Adott típus megjelenési formája

// Logikai literál
true
false

// Szám literál
12
12.34
// Szöveg literál
'Szöveg'
"Szöveg"
`Szöveg`

`Tetszőleges ${kifejezés}`

'Idézőjelben "így" macsakörmölök'
"Macskakörömben 'így' idézek"
'Idézőjelben \' idézőjel'
"Macskakörömben \" macskaköröm"
'Escape: \t \n \\ '

Változók

  • var, let, const kulcsszóval deklarálunk új változót
  • ezek elhagyásával → globális változó – KERÜLENDŐ!!!
  • 'use strict;' – strict mode
  • Ha nincs kezdőérték → undefined
let nev = 'Győző';
let masik;  //undefined

Operátorok

  • Aritmetikai operátorok
    • +, -, *, /, %, ++, --, unáris -, unáris +
  • Értékadás operátorai
    • =, *=, /=, %=, +=, -=, stb.
  • Összehasonlító operátor
    • ==, !=, ===, !==, >, >=, <, <=
    • == és != érték szerint vizsgál (automatikus konverziók)
    • === és !== érték és típus szerint
12 ==  '12'  // true
12 === '12'  // false

Operátorok

  • Logikai operátorok
    • &&, ||, !
  • Szövegösszefűzés operátorai
    • +, +=
  • Bitenkénti operátorok
    • &, |, ^, ~, <<, >>, >>>
  • Speciális operátorok
    • ? : feltételes operátor
    • , több kifejezés végrehajtása egy utasításban, visszatérési értéke az utolsó kifejezés

Vezérlési szerkezetek

// Elágazások
if (felt) {
  utasítások
}

if (felt) {
  utasítások
} else {
  utasítások
}
// Többirányú elágazás
switch(kifejezés) {
  case érték1:
    utasítások
    break;
  case érték2:
    utasítások
    break;
  default:
    utasítások 
}
// Ciklusok
while (felt) {
  utasítások
}

do {
  utasítások
} while (felt);

for (let i=1; i<=n; i++) {
  utasítások
}

A JavaScript nyelv

Függvények

int factorial(int n) {
    int f = 1;
    for (int i=2; i<=n; i++) {
        f *= i;
    }
    return f;
}
function factorial(n) {
    let f = 1;
    for (let i=2; i<=n; i++) {
        f *= i;
    }
    return f;
}

Alapértelmezett értékek

// függvénydeklarációó
function add(a, b = 3) {
  return a + b;
}

// függvényhívás
add(40, 2)      // 42
add(10)         // 13
add(50, 20, 10) // 70
add()           // NaN

Létrehozási formák

// függvénydeklaráció
function add(a, b) {
  return a + b;
}

// függvénykifejezés
const add = function (a, b) {
  return a + b;
}

// fat arrow
const add = (a, b) => {
  return a + b;
}
const add = (a, b) => a + b;

Literálforma

function (a, b) {
  return a + b;
}

// or

(a, b) => a + b

Függvény mint paraméter

function countA(str) {
  let db = 0;
  for (const c of x) {
    if (c === 'a') {
      db++;
    }
  }
  return db;
}

console.log(
  countA("apple")
) // 1

Függvény mint paraméter

function count(str, fn) {
  let db = 0;
  for (const c of x) {
    if (fn(c)) {
      db++;
    }
  }
  return db;
}

console.log(
  count("apple", c => c === 'a')
)

A JavaScript nyelv

Tömb

Létrehozás

Literálforma: []

// creation
const uresTomb = [];
const tomb = [12, 'alma', true];

// referencing an element
tomb[0]; // => 12;
tomb[1]; // => 'alma';
tomb[2]; // => true;

// length
tomb.length // => 3

Módosítás

const tomb = [12, 'alma', true];

// modification
tomb[0] = 13;

// new element at the end
tomb.push("new");

// new element somewhere (not recommended)
tomb[100] = 'far away';
tomb.length; // => 101
tomb[99]; // => undefined

// deleting (size remains the same)
delete tomb[1];
tomb[1]; // => undefined
tomb.length; // => 101

Mátrix

Tömbök tömbje

const m = [
  [1, 2, 3], 
  [4, 5, 6],
];
m[1][2]; // => 6

Iteratív feldolgozás

const gyumolcsok = [
  'alma',
  'korte',
  'szilva'
];

//A gyümölcsök kiírása a konzolra
for (let i = 0; i < gyumolcsok.length; i++) {
  console.log(gyumolcsok[i]);
}

// for..of ciklus (ES6)
for (const gyumolcs of gyumolcsok) {
  console.log(gyumolcs);
}

Tömbfüggvények

Programozási tételek megvalósítása

  • forEach: általános ciklus
  • some: eldöntés
  • every: optimista eldöntés
  • map: másolás
  • filter: kiválogatás
  • reduce: összegzés (sorozatszámítás)
  • find: keresés (elem)
  • findIndex: keresés (index)

Példa – kiválogatás

const numbers = [1, 2, 3, 4, 5];

function filter(x, fn) {
  const out = [];
  for (const e of x) {
    if (fn(e)) {
        out.push(e);
    }
  }
  return out;
}
const evens = filter(numbers, e =>e % 2 === 0);

// instead

const evens = numbers.filter(e =>e % 2 === 0)

Példa – összegzés

function sum(x) {
  let s = 0;
  for (const e of x) {
    s = s + e;
  }
  return s;
}

// instead

x.reduce((s, e) => s + e, 0)

Destructuring and spread

const numbers = [1, 2, 3, 4, 5];
const a = numbers[0];
const b = numbers[1];

// instead
const [a, b] = numbers;

// default values
const [a = 10, b = 20] = [100] // a:100, b:20

// rest
const [a, b, ...rest] = numbers; // --> rest:[3, 4, 5]

// swapping variables
[a, b] = [b, a]

// ignoring
const [a,,b] = numbers; // a:1, b:3

// spread
const a = [1, 2, 3];
const b = [9, ...a, 10]; // b:[9, 1, 2, 3, 10]

A JavaScript nyelv

Objektum

Létrehozás

Literálforma: { }

// creation
const uresObj = {};
const obj = {
  mezo1: 12,
  'mezo2': 'alma',
};

// referencing
obj.mezo1;      // => 12
obj['mezo1'];   // => 12

Módosítás

const obj = {
  mezo1: 12,
  'mezo2': 'alma',
};

// modification
obj.mezo2 = 'korte';

// extending
obj.mezo3 = true;

// deletion
delete obj.mezo1;
obj.mezo1; // => undefined

Metódus (függvény mint adattag)

const obj = {
  data: 42,
  metodus: function () {
    console.log('Foo: ', this.data)
  },
};

obj.metodus();

Getter és setter

const obj = {
  _data: 42,
  get data() {
    return _data;
  },
  set data(value) {
    _data = value;
  }
};

obj.data = 52
obj.data // 52

Dinamikus mezőnév

// Computed property names
const prop = 'foo';
const o = {
  [prop]: 'something',
  ['b' + 'ar']: 'new'
};

o.foo // 'something'
o.bar // 'new'

Objektum

  • Objektum
    • Kulcs-érték párok gyűjteménye
    • Asszociatív tömbhöz hasonlít (hash)
    • Rekord, osztálypéldány szimulálható
  • JavaScriptben nagyon fontos szerepük van
  • Majdnem minden objektum
  • Ha az érték függvény → metódus

Példák

//Tömb az objektumban
const zsofi = {
  kor: 7,
  kedvencEtelek: [
    'krumplipüré',
    'rántott hús',
    'tejberizs'
  ]
};
//Elem elérése
zsofi.kedvencEtelek[1]; 
// => 'rántott hús'
//Objektum az objektumban
const david = {
  kor: 4,
  cim: {
    iranyitoszam: '1241',
    varos: 'Budapest',
    utca: 'Egyszervolt utca',
    hazszam: 63
  }
};
//Elem elérése
david.cim.utca; 
// => 'Egyszervolt utca'

Feldolgozás

const matyi = {
  kor: 1.5,
  fiu: true,
  cuki: true
}

// Feldolgozás a for..in ciklussal
for (const i in matyi) {
  console.log(i, matyi[i]);
}
// Eredmény
// => kor 1.5
// => fiu true
// => cuki true

Adatszerkezetek modellezése

//C++ vector --> JavaScript tömb
const kutyuk = [
  'telefon',
  'fülhallgató',
  'pendrive',
  'e-könyv olvasó'
];
//C++ struct --> JavaScript objektum
const hallgato = {
  nev: 'Mosolygó Napsugár',
  neptun: 'kod123',
  szak: 'Informatika BSc'
};
//Rekordok tömbje
const hallgatok = [
  {
    nev: 'Mosolygó Napsugár',
    neptun: 'kod123',
    szak: 'Informatika BSc'
  },
  {
    nev: 'Kék Ibolya',
    neptun: 'kod456',
    szak: 'Informatika BSc'
  }
];

Adatszerkezetek modellezése

//Tömböt tartalmazó rekordok tömbje
const hallgatok = [
  {
    nev: 'Mosolygó Napsugár',
    neptun: 'kod123',
    szak: 'Informatika BSc',
    targyak: [
      'Programozás',
      'Webfejlesztés 2.',
      'Számítógépes alapismeretek'
    ]
  },
  {
    nev: 'Kék Ibolya',
    neptun: 'kod456',
    szak: 'Informatika BSc',
    targyak: [
      'Programozás',
      'Webfejlesztés 2.',
      'Diszkrét matematika',
      'Testnevelés'
    ]
  }
];

Destructuring and spread

const o = {
  a: 42,
  b: 28,
}
const a = o.a
const b = o.b

// instead
const {a, b} = o;

// renaming
const {a: c, b: d} = o;

// default values
const {a = 10, b = 20} = {a: 42};
const {a: c = 10, b: d = 20} = {a: 42};

// rest
const o = {
  a: 42,
  b: 28,
  c: 12
};
const {a, ...rest} = o; // rest={b:28, c:12}

Destructuring and spread

// nested objects
const david = {
  kor: 4,
  cim: {
    iranyitoszam: '1241',
    varos: 'Budapest',
    utca: 'Egyszervolt utca',
    hazszam: 63
  }
};
const { cim: { utca }} = david

class

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // Method
  calcArea() {
    return this.height * this.width;
  }
}

const square = new Rectangle(10, 10);

console.log(square.area); // 100

class – publikus mezők

class Product {
  name;
  tax = 0.2;
  basePrice = 0;
  price;

  constructor(name, basePrice) {
    this.name = name;
    this.basePrice = basePrice;
    this.price = (basePrice * (1 + this.tax)).toFixed(2);
  }
}

Tesztelés

Példa

function add(a, b) {
  return a + b;
}

Tesztelés a konzolon

Tesztelés a kódban

// saját ellenőrzés
console.log('3 + 2 === 5');
if (add(3, 2) === 5) { console.log('OK')         } 
                else { throw new Error('failed') }
// saját assert függvény
function assert(name, actual, expected) {
    console.log(name);
    if (expected === actual) { 
             console.log('OK')
    } else { console.warn(`failed! ${actual} !== ${expected}`) }
}
assert('3 + 2 should be equal 5',   add(3, 2),   5);
assert('10 + 0 should be equal 10', add(10, 0),  10);
// console.assert
console.assert(add(3, 2)  === 5,   '3 + 2 should be equal 5');
console.assert(add(10, 0) === 10,  '10 + 0 should be equal 10');

Összefoglalás

  • C++ → JavaScript
  • Adatszerkezetek
    • elemi
    • összetett: tömb, objektum
  • Programozási tételek tömbfüggvényekként