Web-Entwicklung

Agenda

Grundlagen

  • HTML/CSS/JS
  • HTTP-Protokoll
  • JSON

Fortgeschrittenes

  • JavaScript
  • Responsive Design
  • NodeJS
  • WebComponents / lit
  • Datenbank

Architektur & Paradigmen

  • Funktionale Programmierung
  • Objektorientierte Programmierung
  • Entwurfsmuster (Singleton, Factory, Builder...)
  • SOLID-Prinzipien
  • Dependency Injection
  • MVC
  • Redux

Interessante Technologien

  • Canvas-Element
  • CSS-Animationen
  • WebSockets
  • WebWorker
  • ServiceWorker
  • WebRTC
  • WebGL
  • Progressive Web Application
  • CEF / Electron
  • WebAssembly

Betrieb

  • Server einrichten
  • SSL- / TLS-Zertifikate

Workflows

  • Git
  • Test Driven Development
  • Continuous Integration / Continuous Delivery

HTML

  • HyperText Markup Language
  • Erste Version 1993 von Tim Berners-Lee
  • Dokumentationsmedium
  • Ursprünglich rein akademische Verwendung
  • Verlinkungen der Dokumente macht sie "hyper"
VersionErscheinungElemente ca.
HTML 1.0199320
HTML 2.0199550
HTML 3.2199770
HTML 4.01199990
HTML 5.02014110
  • Heute ein "lebender Standard" (Living Standard)
  • Stetige inkrementelle Erweiterung

Grundgerüst

							
								
							
						

Beispiel

							
								
							
						

Beispiel

Aufbau eines Elements

							
								
							
						
							
								
							
						
							
								
							
						

CSS

  • Cascading Style Sheet
  • Nach größerer Verbreitung von HTML
  • Webseiten ansprechend gestalten

Beispiel

							
								selector [, selector, selector, ...] {
									property: value;
								}
							
						

Beispiel

							
								html {
									background-color: red;
									font-size: 30px;
								}
							
						

Beispiel

							
								
							
						

Beispielhafte CSS-Eigenschaften

  • background-color: red
  • font-family: Georgia, serif, Arial
  • text-decoration: line-through underline

Selektoren

  • Umfangreiche Element-Selektoren zur Anwendung der Styles
  • Kinder, Enkel...
  • Geschwister, direkte Nachfolger
  • Attribute
  • Pseudoklassen

Selektoren

							
								#my-id /* ID */
								html, body /* Mehrfachselektion */
								div > p /* p die direkt unterhalb eines div sind */
								div  p /* p die irgendwo unterhalb eines div sind */
								a:visited /* besuchte Links */
								div:hover /* divs über die man mit der Maus fährt */
								span.important /* span mit der Klasse "important" */
							
						

Layout

Es gibt zwei grundlegende Blocktypen:

block

inline

Block

Beansprucht eine ganze Zeile und verursacht Zeilenumbrüche

							
								display: block;
							
						

Kann Breite und Höhe haben

							
								display: block;
								width: 20px;
								height: 20px;
							
						

Inline

Wie einfacher Text, der mit anderen in der gleichen Zeile stehen kann

							
								display: inline;
							
						

Festlegen von Breite und Höhe sind wirkungslos

							
								display: inline;
								width: 20px; /* kein Effekt */
								height: 20px; /* kein Effekt */
							
						

Inline-Block

Mischform von inline und block

							
								display: inline-block;
								width: 20px;
								height: 20px;
							
						

Spezifität

Regeln können andere Regeln überschreiben

							
								
							
						
							
								#id:hover { display: none }

								#id { display: block }

								.class.clazz { display: inline }

								div { display: inline-block }
							
						

Box Model

Es gibt zwei Varianten des Modells:

content-box (default)

border-box

							
								box-sizing: content-box;
								box-sizing: border-box;
							
						

Beispiel

							
								div {
									border: 3px solid red;
									padding: 10px;
									width: 100px;
								}

								.border-box {
									box-sizing: border-box;
								}

								.content-box {
									box-sizing: content-box;
								}
							
						
							
								
							
						

Beispiel

Positioning

							
								/* default, da wo es in der Seite steht */
								position: static;
								/* relativ zu seiner eigentlichen Position */
								position: relative;
								/* relativ zu seinem nächsten non-static parent o. window */
								position: absolute;
							
						
							
								position: relative;
								position: absolute;
							
						

erlauben Verschiebung mittels

							
								top: 10px;
								left: 10px;
								right: 10px;
								bottom: 10px;
							
						

Beispiel Menü

							
								.menu-item {
									display: inline-block;

									position: relative;
								}

								.menu-item .children {
									display: none;

									position: absolute;
								}

								.menu-item:hover .children {
									display: block;
								}
							
						
							
								
							
						

JS

  • JavaScript stammt aus dem Jahr 1995 von Netscape
  • Syntaktisch an Java angelehnt
  • Ursprünglich nur optionale, verzichtbare Effekte (unobstrusive)
  • Mittlerweile von ECMA standardisiert
VersionECMA StandardJahr
ES1ECMAScript 11997
ES2ECMAScript 21998
ES3ECMAScript 31999
ES5ECMAScript 52009
ES6ECMAScript 20152015
...
ECMAScript 20202020

Code wird zwischen script-Tags geschrieben

							
								<!DOCTYPE html>
								<html lang="de">
									<head>
										<meta charset="UTF-8">
									</head>
									<body>
										<script>// code</script>
									</body>
								</html>
							
						

DOM-API

							
								// findet das erste Element
								const parent = document.querySelector("#id");

								// findet alle Elemente
								const elements = document.querySelectorAll("#id");

								// Element erstellen
								const newElement = document.createElement("div");

								newElement.addEventListener("click", (event) => {
									// Click-Event
								});

								// Element anhängen
								parent.appendChild(newElement);

								newElement.remove();
							
						

Auslagern in verschiedene Dateien

							
								<!DOCTYPE html>
								<html>
									<head>
										
										
									</head>
									<body>
										
										<script src="index.js"></script>
									</body>
								</html>
							
						

Parsen eines HTML-Dokuments

							
								
							
						

Verschiedene Varianten, JavaScript erst am Ende auszuführen

Damals mit jQuery:

							
								<!DOCTYPE html>
								<html>
									<head>
										<script>
											$(document).ready((event) => {
												const element = document.querySelector("#hello");
											});
										</script>
									</head>
									<body>
										
Hello World!
</body> </html>

script-Tag am Ende

							
								<!DOCTYPE html>
								<html>
									<head>
									</head>
									<body>
										
Hello World!
... <script src="index.js"></script> </body> </html>

Event-basiert, z.B. per DOMContentLoaded

							
								<!DOCTYPE html>
								<html>
									<head>
										<script>
											document.addEventListener("DOMContentLoaded", (event) => {
												// wird ausgeführt, sobald das Dokument geparst wurde
												const element = document.querySelector("#hello");
											});
										</script>
									</head>
									<body>
										
Hello World!
</body> </html>

Moderne Variante

							
								<script src="index.js" defer></script>
							
						

document-Operationen

							
								document.open();
								document.write("
Booo!
"); document.close();
							
								<body>
									<script>document.write("

Dies ist ein Text.

")</script> <script> const button = document.querySelector("button"); button.addEventListener("click", () => { document.write("Und pfutsch!"); }); </script> </body>

HTTP-Protokoll

  • OSI-Schichten 5, 6 und 7
  • Anfrage-Antwort-Prinzip
  • Basiert auf einfachem Text
VersionJahr
0.91991
1.01996
1.11999
2.02015
3.02022

Request an www.google.de

							
								GET / HTTP/1.1
								Host: www.google.de
								User-Agent: curl/7.88.1
								Accept: */*
							
						

Response von www.google.de

							
								HTTP/1.1 200 OK
								Date: Tue, 04 Apr 2023 15:45:26 GMT
								Expires: -1
								Cache-Control: private, max-age=0
								Content-Type: text/html; charset=ISO-8859-1
								Content-Security-Policy-Report-Only: [...]
								Server: gws
								X-XSS-Protection: 0
								X-Frame-Options: SAMEORIGIN
								Set-Cookie: [...]
								Accept-Ranges: none
								Vary: Accept-Encoding
								Transfer-Encoding: chunked
								
								<!doctype html><html>...</html>
							
						

Einfach mal testen:

							
								curl -v --http1.0 http://www.google.de
								curl -v --http1.1 http://www.google.de
								curl -v --http2 http://www.google.de
								curl -v --http2-prior-knowledge http://www.google.de
								curl -v --http3 http://www.google.de
							
						

Verschiedene "Verben" bzw. "Methoden"

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE
  • ...

Beispiel:

							
								git clone https://git.furnco.de/r/public/web-development/examples.git
								cd examples/templates/005-http-rest
								node index.js
							
						
							
								curl -X GET -is http://localhost:3000/todo
								curl -X POST -H "Content-Type: application/json" -d '{"name": "Einkaufen"}' -is http://localhost:3000/todo
								curl -X POST -H "Content-Type: application/json" -d '{"name": "Putzen"}' -is http://localhost:3000/todo
								curl -X PUT -H "Content-Type: application/json" -d '{"name": "Schlafen"}' -is http://localhost:3000/todo/1
								curl -X DELETE -is http://localhost:3000/todo/0
							
						
							
								HTTP/1.1 200 OK
								X-Powered-By: Express
								Content-Type: application/json; charset=utf-8
								Content-Length: 13
								ETag: W/"d-KMmUcQ1kigqtwzZnU+jVDkYP3Co"
								Date: Wed, 05 Apr 2023 12:05:05 GMT
								Connection: keep-alive
								Keep-Alive: timeout=5
								
								["Einkaufen"]
							
						
							
								app.get("/todo", (req, res) => {
									return res.json(todos);
								});
								
								// [...]
								
								app.post("/todo", (req, res) => {
									// [...]
										return res.json(todos);
									// [...]
								});
							
						

GET und POST auf klassischen Webseiten

							
								

Beispiel:

							
								cd examples/templates/006-http-web
								node index.js
							
						

JSON

  • JavaScript Object Notation
  • Basiert auf reinem Text
  • Format zur strukturierten Speicherung von Daten
  • Attribute müssen immer in doppelte Anführungsstriche (") gesetzt werden

Definition eines einfachen Objekts in JS

							
								const o = {
									x: 1,
									y: 2
								};
							
						

Entsprechung in JSON

							
								{
									"x": 1,
									"y": 2
								}
							
						

Mögliche Typen

  • Number (bzw. Integer / Float)
  • Boolean
  • String
  • Array
  • Object

Der äußere Container kann ein Array oder ein Object sein

							
								{
									"key": "value",
								}
							
						
							
								[
									"foo",
									"bar"
								]
							
						

JavaScript

c / c++ Java C# JS
Formale Spezifikation ja
Übersetzung Nativ kompiliert Bytecode Interpretiert / kompiliert (JIT)
Typisierung statisch dynamisch
Speicher-Management Manuell Garbage Collector

Begrifflichkeiten

							
								function add(x, y) {
									return x + y;
								}
								
								const a = 5;
								const b = add(a, 6);
								const c = [];
							
						
Operator, Aufruf (Call), Ausdruck (Expression), Parameter, Argument, Literal,
Zuweisung (Assignment), Linke Hand (Left hand), Rechte Hand (Right hand)

Vorbereiten der Beispiele (bei Bedarf)

							
								# im Ordner 'examples/'
								. hooks/post-checkout
							
						

Ausführung

							
								# node [Script-Datei], z.B.
								node index.js
							
						

Ausgaben

							
								console.log("Hello World!");
							
						

Variablen

							
								//  < es6
								var x = 1;
								
								// >= es6
								let y = 2;
								const z = 3;
							
						
							
								var yes = false;

								if (yes) {
									var a = 1;
								}
								
								console.log(a);
							
						
							
								undefined
							
						
							
								var yes = false;

								if (yes) {
									let a = 1;
								}
								
								console.log(a);
							
						
							
								ReferenceError: a is not defined
							
						
							
								function foo() {
									var yes = false;
								
									if (yes) {
										var a = 1;
									}
								}
								
								foo();
								
								console.log(a);
							
						
							
								ReferenceError: a is not defined
							
						

var

  • hat function-Scope
  • wird durch hoisting ("hochziehen") aus dem Block heraus an den Start der Funktion gezogen
							
								var yes = false;
								var a;

								if (yes) {
									a = 1;
								}
								
								console.log(a);
							
						

let, const

  • haben intuitiven Block-Scope (wie viele andere Programmiersprachen auch)
  • daher nur an Ort und Stelle gültig in der angegebenen Reihenfolge

Datentypen

							
								let x = 5; // Number (Integer)
								let f = 1.25; // Number (Float)
								let b = true; // Boolean
								let s = "hallo"; // String
								let a = []; // Array
								let o = {}; // Objekt
								let nan = NaN; // Not a Number
								let n = null; // Null
								let u = undefined; // Undefiniert
							
						

Alternation

							
								if (x == 1) {
									// Code
								}
								else if (x == 2) {
									// alternativer Code
								}
								else {
									// Fallback
								}
							
						

Schleifen

							
								for (let i = 0; i < 5; i++) {
									// Code
								}
							
						
							
								const a = [1, 2, 3];
								
								for (const element of a) {
									// Code
								}
							
						
							
								while (i == 1) {
									// Code
								}
							
						
							
								do {
									// Code
								} while (i == 1)
							
						

Arrays

							
								let a = [1, 2, 3];
								
								a.push(4);
								a.push(5);
								
								a.pop();
								
								console.log(a);
							
						
							
								[1, 2, 3, 4]
							
						

Objekte

							
								let o = {x: 1, y: 2};
								
								console.log(o.z);
								
								console.log(o);
								
								o.z = 3;
								
								console.log(o);
							
						
							
								undefined
								{ x: 1, y: 2 }
								{ x: 1, y: 2, z: 3 }
							
						
Objekte funktionieren intern wie Hash-Maps
							
								let o = {};
								
								o.a = 1;
								o["a"] = 1; // alternativ
								
								o["$ !"] = 2; // so sind auch komplexe Schlüssel möglich
								
								// o."$ !" = 2; => Syntaxfehler
								// o.$ ! = 2; => Syntaxfehler
								
								o[true] = 3;
								
								console.log(Object.keys(o));
							
						
							
								[ 'a', '$ !', 'true' ]
							
						

Funktionen

							
								function foo() {
									console.log("foo");
								}
								
								function bar(a) {
									return a;
								}
								
								foo();
								
								const a = bar(1);
								
								console.log(a);
							
						
							
								foo
								1
							
						
							
								let sum = function(a, b) {
									return a + b;
								}
								
								let subtract = function() {
									console.log(arguments);
								
									return arguments[0] - arguments[1];
								}
								
								console.log(sum(1, 2));
								console.log(subtract(1, 2));
							
						
							
								3
								[Arguments] { '0': 1, '1': 2 }
								-1
							
						

Funktionen als Konstruktor

							
								function Rectangle(a, b) {
									this.a = a;
									this.b = b;
								}
								
								const r = new Rectangle(2, 3);
								
								console.log(r.a);
							
						
							
								2
							
						

Objektorientierung

							
								function Rectangle(a, b) {
									this.a = a;
									this.b = b;
								}
								
								// jede Funktion besitzt einen Prototypen
								Rectangle.prototype.getArea = function() {
									return this.a * this.b;
								}
								
								const r1 = new Rectangle(2, 3);
								const r2 = new Rectangle(4, 5);
								
								console.log(r1.getArea());
								console.log(r2.getArea());
							
						
							
								6
								20
							
						
Dynamische Änderung des Prototypen
							
								function Rectangle(a, b) {
									this.a = a;
									this.b = b;
								}
								
								const r = new Rectangle(2, 3);
								
								console.log(r.getArea);
								
								Rectangle.prototype.getArea = function() {
									return this.a * this.b;
								}
								
								console.log(r.getArea);
							
						
							
								undefined
								[Function (anonymous)]
							
						

Aufgabe

Bringe dem Array eine Methode bei, welche die Summe aller enthaltenen Zahlen zurückgibt
							
								const a = [1, 2, 3];
								
								console.log(a.sum());
							
						
							
								6
							
						

Lösung

							
								Array.prototype.sum = function() {
									let sum = 0;
								
									for (let number of this) {
										sum += number;
									}
								
									return sum;
								}
							
						

Vererbung

							
								// Oberklasse
								function Shape() {
								}
								
								Shape.prototype.getType = function() {
									return "Shape";
								}
								
								// Unterklasse
								function Rectangle(a, b) {
									this.a = a;
									this.b = b;
								}
								
								// Prototype der Oberklasse in die Unterklasse kopieren
								Rectangle.prototype = Object.create(Shape.prototype);
								// Konstruktor der Oberklasse am Prototypen durch den eigenen ersetzen
								Rectangle.prototype.constructor = Rectangle;
								
								const r = new Rectangle(2, 3);
								
								console.log(r.getType());
								
								// .getType() selber implementieren
								Rectangle.prototype.getType = function() {
									return "Rectangle";
								}
								
								console.log(r.getType());
							
						
							
								Shape
								Rectangle
							
						

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

Objektorientierung in es6

							
								class Rectangle {
									constructor(a, b) {
										this.a = a;
										this.b = b;
									}
								
									getArea() {
										return this.a * this.b;
									}
								}
								
								const r = new Rectangle(2, 3);
								
								console.log(r.getArea());
							
						
							
								6
							
						

Vererbung in es6

							
								// Oberklasse
								class Shape {
									getType() {
										return "Shape";
									}
								}
								
								// Unterklasse erbt von Oberklasse
								class Rectangle extends Shape {
									constructor(a, b) {
										super();
								
										this.a = a;
										this.b = b;
									}
								}
								
								const r = new Rectangle(2, 3);
								
								console.log(r.getType());
								
								// Implementierung per Prototype weiterhin möglich, falls man so will
								Rectangle.prototype.getType = function() {
									return "Rectangle";
								}
								
								console.log(r.getType());
							
						
							
								Shape
								Rectangle
							
						

Asynchronität

Asynchron: Es wird nicht auf die Beendigung des Befehls gewartet, sondern mit dem Programm fortgefahren. Die Vollendung des asynchronen Befehls tritt irgendwann in der Zukunft ein.

							
								setTimeout(callback, time); // Ausführung nach [time] Millisekunden
								setInterval(callback, interval); // Ausführung alle [interval] Millisekunden
							
						
							
								setTimeout(function() {
									// Code, der nach 2 Sekunden ausgeführt wird
									console.log("zweiter");
								}, 2000);
								
								console.log("erster");
							
						
							
								erster
								zweiter
							
						

Aufgabe: Schreibe ein Programm, das zwei weitere beliebige Texte mit jeweils 2 Sekunden Verzögerung von einander ausgibt, d.h.

"erster" -> 2s -> "zweiter" -> 2s -> "Text A" -> 2s -> "Text B"

							
								setTimeout(function() {
									console.log("zweiter");
								
									// weiterer Code
								}, 2000);
								
								console.log("erster");
							
						
Lösung: Callback-Hell oder Pyramide des Todes
							
								setTimeout(function() {
									console.log("zweiter");
								
									setTimeout(function() {
										console.log("Text A");
								
										setTimeout(function() {
											console.log("Text B");
										
											
										}, 2000);
									}, 2000);
								}, 2000);
								
								console.log("erster");
							
						
Hilfsmittel: Promises
							
								new Promise(function (resolve, reject) {
									// ich bin fertig
									resolve();
								
									// es ist ein Fehler aufgetreten
									reject();
								});
							
						
							
								const p = new Promise(function (resolve, reject) {...});
								const p2 = new Promise(function (resolve, reject) {...});
								const p3 = new Promise(function (resolve, reject) {...});
								const p4 = new Promise(function (resolve, reject) {...});
								
								p
									.then(function() { return p2; })
									.then(function() { return p3; })
									.then(function() { return p4; });
							
						
							
								console.log("erster");
								
								delay(2000)
									.then(function () {
										console.log("zweiter");
								
										return delay(2000);
									})
									.then(function() {
										console.log("Text A");
								
										return delay(2000);
									})
									.then(function() {
										console.log("Text B");
									})
							
						
Aufgabe: Implementiere die Funktion "delay"
							
								const delay = function() {
									// implementieren
								}
								
								console.log("erster");
								
								delay(2000)
									.then(function () {
										console.log("zweiter");
								
										return delay(2000);
									})
									.then(function() {
										console.log("Text A");
								
										return delay(2000);
									})
									.then(function() {
										console.log("Text B");
									})
							
						
Lösung:
							
								const delay = function(ms) {
									return new Promise(function(resolve, reject) {
										setTimeout(function() {
											resolve();
										}, ms);
									});
								}
								
								console.log("erster");
								
								delay(2000)
									.then(function () {
										console.log("zweiter");
								
										return delay(2000);
									})
									.then(function() {
										console.log("Text A");
								
										return delay(2000);
									})
									.then(function() {
										console.log("Text B");
									})
							
						
Rückgabewerte mit Promises
							
								const p = new Promise(function(resolve, reject) {
									resolve("ok");
								});
								
								p.then(function(value) {
									console.log(value);
								});
							
						
							
								ok
							
						
Fehlerbehandlung mit Promises
							
								const p = new Promise(function(resolve, reject) {
									reject(new Error("Fehler"));
								});
								
								p
									.then(function() {
										console.log("Ich werde nicht aufgerufen")
									})
									.catch(function(e) {
										console.log(e.message);
									});
							
						
							
								Fehler
							
						
Datei lesen mit NodeJS
							
								const fs = require("fs");
								
								fs.readFile("./hello.txt", {encoding: "utf8"}, function(error, data) {
									console.log(data);
								});
							
						
							
								Hello World!
							
						
Aufgabe: "Promisifiziere" analog zu "delay" in der letzten Aufgabe den Aufruf von fs.readFile()
							
								const fs = require("fs");
								
								function readFile() {
									// implementieren
								}
								
								readFile("./hello.txt").then(function(content) {
									console.log(content);
								});
							
						
							
								Hello World!
							
						
Lösung:
							
								const fs = require("fs");
								
								function readFile(path) {
									return new Promise(function (resolve, reject) {
										fs.readFile(path, {encoding: "utf8"}, function(error, data) {
											resolve(data);
										});
									});
								}
								
								readFile("./hello.txt").then(function(content) {
									console.log(content);
								});
							
						
							
								Hello World!
							
						
Aufgabe: Nutze die vorherige Lösung nun für eine Promise-Kette, sodass die Inhalte der zwei Dateien "hello.txt" und "hallo.txt" nacheinander ausgegeben werden:
							
								Hello World!
								
								Hallo Welt!
								
							
						
Lösung:
							
								const fs = require("fs");
								
								function readFile(path) {
									return new Promise(function (resolve, reject) {
										fs.readFile(path, {encoding: "utf8"}, function(error, data) {
											resolve(data);
										});
									});
								}
								
								readFile("./hello.txt")
									.then(function(content) {
										console.log(content);
								
										return readFile("./hallo.txt");
									})
									.then(function(content) {
										console.log(content);
									});
							
						
							
								Hello World!
								
								Hallo Welt!
							
						

Async - Await

  • Syntaktischer Zucker für Promises
  • Nutzung von await nur im Kontext einer async-Funktion möglich
							
								async function wrapper() {
									const p = new Promise(function(resolve, reject) {
										resolve("Hello from Promise!");
									});
									
									const result = await p;
									
									console.log(result);
								}
								
								wrapper();
							
						
							
								Hello from Promise!
							
						
Aufgabe: Schreibe die Lösung der vorherigen Aufgabe nach Async - Await um
Lösung:
							
								const fs = require("fs");
								
								function readFile(path) {
									return new Promise(function (resolve, reject) {
										fs.readFile(path, {encoding: "utf8"}, function(error, data) {
											resolve(data);
										});
									});
								}
								
								async function wrapper() {
									const content1 = await readFile("./hello.txt");
									const content2 = await readFile("./hallo.txt");
								
									console.log(content1);
									console.log(content2);
								}
								
								wrapper();
							
						
							
								Hello World!
								
								Hallo Welt!
							
						

Destructuring

Auflösen von komplexen Strukturen

							
								// Objekt destrukturieren (per Attribut-Namen)
								const { a, b } = { a: 1, b: 2 };
								
								console.log(a);
								console.log(b);
								
								// Array destrukturieren (per Position)
								const [ c, d ] = [3, 4];
								
								console.log(c);
								console.log(d);
							
						
							
								1
								2
								3
								4
							
						
							
								// Bei Objekten Elemente umbenennen oder auch auslassen
								const { a: x, b: y } = { a: 1, b: 2, c: 3 };
								
								console.log(x);
								console.log(y);
								
								// Bei Arrays Elemente auslassen
								const [ , a, b, , c] = [3, 4, 5, 6, 7, 8];
								
								console.log(a);
								console.log(b);
								console.log(c);
							
						
							
								1
								2
								4
								5
								7
							
						
							
								// Verschachteltes Destructuring
								const {a: [, x, ] } = { a: [0, 1, 2]};
								
								console.log(x);
							
						
							
								1
							
						
Aufgabe: x soll die 5 enthalten
							
								const o = { a: [0, {b: [0, 5]}, 2]};
								
								const  { /* Destructuring-Ausdruck */ } = o;
								
								console.log(x);
							
						
							
								5
							
						
Lösung:
							
								const o = { a: [0, { b: [0, 5] }, 2]};

								const { a: [, { b: [, x] }]} = o;
								
								console.log(x);
							
						
							
								5
							
						
Aufgabe: x soll die 3 enthalten
							
								const o = { a: [0, {b: [0, { c: [{ x: 5 }, { d: 3}] }]}, 2]};
								
								const  { /* Destructuring-Ausdruck */ } = o;
								
								console.log(x);
							
						
							
								3
							
						
Lösung:
							
								const o = { a: [0, {b: [0, { c: [{ x: 5 }, { d: 3}] }]}, 2]};

								const  { a: [, {b: [, { c: [, { d: x}] }] }] } = o;
								
								console.log(x);
							
						
							
								3
							
						

Destructuring zum parallelen Ausführen von mehreren Promises

							
								const fs = require("fs");
								
								function readFile(path) {
									return new Promise(function (resolve, reject) {
										fs.readFile(path, {encoding: "utf8"}, function(error, data) {
											resolve(data);
										});
									});
								}
								
								async function wrapper() {
									const [ content1, content2 ] = await Promise.all([
										readFile("./hello.txt"),
										readFile("./hallo.txt")
									]);
								
									console.log(content1);
									console.log(content2);
								}
								
								wrapper();
							
						

Try-Catch-Finally

							
								function throwError() {
									try {
										throw new Error("Fehler!");
										return "Hello World!";
									}
									catch (e) {
										return e.message;
									}
									finally {
										console.log("Finally wird immer ausgeführt");
										return "Finally!";
									}
								}
								
								const result = throwError();
								console.log(result);
							
						
							
								Finally wird immer ausgeführt
								Finally!
							
						

Anwendungsbeispiel für Try-Catch-Finally

							
								function readFromDatabase() {
									try {
										db.connect();
										return db.read();
									}
									catch (e) {
										console.log(e.stack);
										return "";
									}
									finally {
										if (db.open) {
											db.close();
										}
									}
								}
							
						

Scope

							
								function a() {
									const x = 5;
								
									return function() {
										return x * x;
									};
								}
								
								const squareX = a();
								const result = squareX();
								
								console.log(result);
							
						
							
								25
							
						

this

							
								class MyClass {
									constructor(a) {
										this.a = a;
									}
								
									getA() {
										return this.a;
									}
								}
								
								const x = new MyClass(5);
								const y = new MyClass(10);
								
								console.log(x.getA());
								console.log(y.getA());
							
						
							
								5
								10
							
						
							
								global.a = 5;

								function foo() {
									this.a += 10;
								}
								
								foo();
								
								console.log(a);
							
						
							
								15
							
						
							
								class MyClass {
									/* ... */
									setA() {
										function f() {
											this.a += 100;
										}
										f();
									}
								}
								
								const x = new MyClass(5);
								
								x.setA();
								
								console.log(x.getA());
							
						
							
								TypeError: Cannot read property 'a' of undefined
							
						
							
								class MyClass {
									/* ... */
									setA() {
										const me = this;
										function f() {
											me.a += 100;
										}
										f();
									}
								}
								
								const x = new MyClass(5);
								
								x.setA();
								
								console.log(x.getA());
							
						
							
								105
							
						

Arrow-Funktionen

  • Kompakte Schreibweise einer normalen Funktion
  • Bei Einzeilern ist das return nicht notwendig
  • this-Pointer des aktuellen Kontextes wird beibehalten
							
								// Einzeiler
								const f1 = _ => 1;
								const f2 = () => 1;
								const f3 = (x) => x * x;
								const f4 = (x, y) => x + y;
								
								// Mehrzeiler
								const f5 = (x, y) => {
									return x * y;
								};
							
						
							
								class MyClass {
									/* ... */
									setA() {
										const f = () => {
											this.a += 100;
										}
										f();
									}
								}
								
								const x = new MyClass(5);
								
								x.setA();
								
								console.log(x.getA());
							
						
							
								105
							
						

Generator-Funktionen

							
								function* generator() {
									let i = 0;
								
									while(true) {
										yield i;
										i++;
									}
								}
								
								const g = generator();
								
								console.log(g.next().value);
								console.log(g.next().value);
								console.log(g.next().value);
							
						
							
								1
								2
								3
							
						

Generator-Funktionen

							
								function* generator() {
									yield 1;
									yield 2;
									yield 3;
								}
								
								const g = generator();
								
								for (const i of g) {
									console.log(i);
								}
							
						
							
								1
								2
								3
							
						

Nützliche Array-Funktionen

Aufgabe: Schreibe ein Programm, das den Gesamtumsatz aus dem ersten Halbjahr berechnet
							
								const revenues = [
									{month: 0, revenue: 1000},
									{month: 1, revenue: 2000},
									{month: 2, revenue: 3000},
									{month: 3, revenue: 4000},
									{month: 4, revenue: 5000},
									{month: 5, revenue: 6000},
									{month: 6, revenue: 6000},
									{month: 7, revenue: 5000},
									{month: 8, revenue: 4000},
									{month: 9, revenue: 3000},
									{month: 10, revenue: 2000},
									{month: 11, revenue: 1000}
								];
								
								let totalRevenue = 0;
								
								/* ... */
								
								console.log(totalRevenue);
							
						
Lösung
							
								totalRevenue = revenues
									.filter((revenue) => revenue.month < 6)
									.map((revenue) => revenue.amount)
									.reduce((sum, amount) => sum + amount, 0);
							
						
							
								21000
							
						
							
								const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
								
								a.filter((e) => e > 2); // Filterung
								a.map((e) => e * 2); // Umformung
								a.reduce((p, e) => p + e, 0); // Zusammenrechnung / Reduzierung
								a.some((e) => e > 5); // true wenn min. ein Element die Bedingung erfüllt
								a.every((e) => e > 5); // true wenn alle Elemente die Bedingung erfüllen