mirror of
https://github.com/TheTaz25/denis.ergin.git
synced 2025-07-07 16:18:50 +00:00
feat(slides): add slides for complex-datatypes
This commit is contained in:
parent
48e2ddc3b3
commit
44d5becbd1
5 changed files with 443 additions and 0 deletions
|
@ -0,0 +1,173 @@
|
|||
<section>
|
||||
<section>
|
||||
<h2>Arrays</h2>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Arrays sind ähnlich zu Objekten komplexe Objekte die im Heap allokiert werden.</p>
|
||||
<p>Arrays können beliebig viele Daten beinhalten und haben keine feste Größe. (Es können aber Arrays mit einer bestimmten Länge initialisiert werden.)</p>
|
||||
<p>Die Inhalte eines Arrays können beliebig sein.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [5, '42', false, {}, [], undefined, null];
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Die Länge eines Arrays steht in der Property "length"</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [1,2,3,4,5];
|
||||
|
||||
// 5
|
||||
console.log(arr.length);
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Aus persönlicher Sicht sind Arrays der alltäglichste Datentyp mit dem man Arbeiten wird.</p>
|
||||
<ul>
|
||||
<li>Liste an Blogeinträgen zum Anzeigen</li>
|
||||
<li>Inhalte eines Blogeintrages</li>
|
||||
<li>Produktlisten</li>
|
||||
<li>Menüeintrage</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Array-Funktionen</h3>
|
||||
</section>
|
||||
|
||||
<!-- Bool Checks -->
|
||||
<section>
|
||||
<p>.every()</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [15, 25, 765, 11];
|
||||
|
||||
// true
|
||||
console.log(arr.every((value) => value > 10));
|
||||
</code></pre>
|
||||
<p>Prüft, ob jedes Element im Array einer gegebenen Prüfung standhält. Nur <code>true</code> wenn alle Elemente dem Test bestehen.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>.filter()</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [5, 24, 1, 9, 22];
|
||||
|
||||
// [24, 22]
|
||||
console.log(arr.filter((value) => value > 10));
|
||||
</code></pre>
|
||||
<p>Prüft alle Elemente eines Arrays. Die Elemente die die Prüfung bestehen, werden in einem neuen Array zurück gegeben. Das originalle Array wird nicht modifiziert.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>.find()</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [5, 24, 1, 9, 22];
|
||||
|
||||
// 24
|
||||
console.log(arr.find((value) => value > 10));
|
||||
</code></pre>
|
||||
<p>Prüft die Elemente eines Arrays. Das erste Element, dass die Prüfung besteht wird zurück gegeben.</p>
|
||||
<p>Es existiert eine alternative Methode .findIndex(), die Funktion liefert den Index des Elementes anstatt das Elementes selbst das gefunden wurde.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>.includes()</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [5, 24, 1, 9, 22];
|
||||
|
||||
// true
|
||||
console.log(arr.includes(22));
|
||||
</code></pre>
|
||||
<p>Prüft ob im Array ein gesuchtes Element vorhanden ist. Aufgrund der Art wie Elemente gespeichert werden, sollte darauf geachtet werden das es zu ungewollten Problemen mit komplexen Datentypen kommen kann.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = {};
|
||||
const arr = [obj];
|
||||
|
||||
// true
|
||||
console.log(arr.includes(obj));
|
||||
|
||||
// false
|
||||
console.log(arr.includes({}));
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>.map()</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [1, 2, 3, 4, 5];
|
||||
|
||||
// [1, 4, 9, 16, 25]
|
||||
console.log(arr.map((value) => value * value));
|
||||
</code></pre>
|
||||
<p>Erzeugt ein neues Array. Jedes Element wird in einer Funktion modifiziert und in ein neues Array gepackt. Das alte Array bleibt unberührt.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>push & pop</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [1, 2, 3];
|
||||
arr.push(4);
|
||||
|
||||
// [1, 2, 3, 4]
|
||||
console.log(arr);
|
||||
|
||||
// 4
|
||||
console.log(arr.pop());
|
||||
|
||||
// [1, 2, 3]
|
||||
console.log(arr);
|
||||
</code></pre>
|
||||
<p>Modifiziert das Array in dem es Elemente am Ende mit <code>push</code> hinzufügt, und mit <code>pop</code> aus dem Ende heraus nimmt.</p>
|
||||
<p>Bei der <code>pop</code>-Funktion wird das entfernte Element zurück gegeben.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>.reduce()</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [1,2,3,4];
|
||||
|
||||
// 10
|
||||
console.log(arr.reduce((acc, val) => {
|
||||
acc += val;
|
||||
}, 0));
|
||||
</code></pre>
|
||||
<p>Kalkuliert einen Wert basierend aus den Elementen des Array. Das Array erwartet 2 Werte: eine Funktion in der ein Accumulator und der aktuelle Wert als Parameter übergeben wird und den nächsten Wert zurück geben soll. Und den initialen Wert das Accumulators.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>some</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [1, 5, 10, 25];
|
||||
|
||||
// true
|
||||
console.log(arr.some((value) => value > 10));
|
||||
</code></pre>
|
||||
<p>Prüft ob mindestens ein Element des Arrays die Prüfung besteht. Wenn das nicht der Fall ist wird ein <code>false</code> zurück gegeben.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>.sort()</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const arr = [1, 10, 5];
|
||||
|
||||
a.sort((a, b) => a - b);
|
||||
|
||||
// [1, 5, 10]
|
||||
console.log(a);
|
||||
</code></pre>
|
||||
<p>Sortiert das Array "In Place" (Ursprüngliches Array wird modifiziert).</p>
|
||||
<p>Hierzu führt <code>sort</code> eine Funktion aus, die mitgegeben wird. Anhand des Ergebnisses werden Elemente im Array umsortiert</p>
|
||||
<ul>
|
||||
<li>Ergebnis -1: Wert "a" ist kleiner als Wert "b"</li>
|
||||
<li>Ergebnis 1: Wert "a" ist größer als Wert "b"</li>
|
||||
<li>Ergebnis 0: Wert "a" und "b" sind gleich, Positionen behalten</li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
import Title from './title.astro';
|
||||
import Objects from './objects.astro';
|
||||
import Arrays from './arrays.astro';
|
||||
---
|
||||
|
||||
<div class="slides">
|
||||
<Title />
|
||||
<Objects />
|
||||
<Arrays />
|
||||
</div>
|
|
@ -0,0 +1,248 @@
|
|||
<section>
|
||||
<section>
|
||||
<h2>Objekte in JavaScript</h2>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Objekte in JS sind eine der wichtigstens Grundpfeiler, die die Sprache so mächtig machen.</p>
|
||||
<p>In JavaScript ist das Objekt das alles Abbildet (in Fakt, alles in JavaScript ist ein Objekt, auch die anderen Datentypen).</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Definition eines Objektes</h3>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Anders als bei Sprachen mit strikten Datentypen (und Klassen die eine fest Vorgegebene Struktur aufweisen), kann ein Objekt in JavaScript dynamisch erstellt und modifiziert werden.</p>
|
||||
<p>Objekte kommen am einem Key-Value-Speicher an nahesten. Ein Key kann dabei ein beliebiger string sein, der Wert kann alles annehmen.</p>
|
||||
<p>Ein Objekt wird einfach mit Geschweiften (Curly) Klammern definiert.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const meinObjekt = {
|
||||
key: "value",
|
||||
numeric: 5,
|
||||
boolean: false,
|
||||
}
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Objekte können auch ineinander geschachtelt werden (in beliebiger Tiefe)</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const geschachtelt = {
|
||||
level1: {
|
||||
level2: {
|
||||
level3: {
|
||||
level4: "Und so weiter...",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Auch wenn JS diese Flexibilität bietet, sollte die Datenstruktur möglichst flach gehalten werden.</p>
|
||||
<p>Spätestens im Backend muss dieselbe Datenstruktur aufgebaut werden. Falls nicht eine dynamische Sprache wie JS verwendet ist, haben tief geschachtelte Objekte einen großen Mehraufwand im Backend.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Zugriffe auf Inhalte in einem Objekt können über 2 Wege erreicht werden</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = {
|
||||
value: 5,
|
||||
nested: {
|
||||
value: 42,
|
||||
},
|
||||
};
|
||||
|
||||
// Dot-Notation
|
||||
console.log(obj.nested.value);
|
||||
|
||||
// Array-Like-Access
|
||||
console.log(obj['nested']['value']);
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Gängig ist die Verwendung der dot-notation, hier ist aber das Wissen der keys zur Entwicklungszeit notwendig.</p>
|
||||
<p>Wenn programmatisch auf die Inhalte Zugegriffen werden soll, kann dies nur über die Array-Notation geschehen.</p>
|
||||
<p>Zusätzlich ist die Array-Notation notwendig, wenn Zeichen verwendet werden, die bereits eine andere Verwendung haben (Beispiel "-", " ")</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = {
|
||||
value: 42;
|
||||
"with-minus": "",
|
||||
};
|
||||
|
||||
console.log(obj['with-minus']);
|
||||
|
||||
// error: console.log(obj.with-minus);
|
||||
|
||||
const key = 'with-minus';
|
||||
console.log(obj[key]);
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Inhalte in Objekten können auch beliebig geändert werden</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = {
|
||||
value: 5,
|
||||
};
|
||||
|
||||
obj.value = 42;
|
||||
|
||||
console.log(obj.value);
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Unstimmigkeit gefunden?</p>
|
||||
<p><code>obj</code> wurde mit const initialisiert, dessen Inhalt kann aber manipuliert werden.</p>
|
||||
<p>Mein Fehler? Nein. Das ist JavaScript und seine Komplexen Datentypen funktionieren so.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Wir müssen nun erstmal verstehen was der Unterschied zwischen simplen und komplexen Datentypen ist, und was das für Folgen hat.</p>
|
||||
<p>JavaScript speichert simple Datentypen wie Zahlen oder Strings in Stack ähnlichen Speicher.</p>
|
||||
<p>Komplexe Objekte werden im Heap allokiert.</p>
|
||||
<p>Das alles ist eine vereinfachte Darstellung. Die internen Vorgänge sind viel komplexer und für den Alltag eines Web-Developers auch nicht notwendig.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Kurzer Recap: Heap vs Stack</p>
|
||||
<p>Inhalte im Stack sind direkt erreichbar und bilden einen LIFO-Speicher (Last-In-First-Out). Die Daten müssen eine Feste Größe haben, zum Vorteil eines schnellen Zugriffs.</p>
|
||||
<p>Der Heap stellt einen größeren Speicherbereich da, in dem Inhalte dynamisch abgelegt werden können.</p>
|
||||
<p>Im Heap können dynamische / komplexe Datenstrukturen mittels einer Speicherreferenz verwendet werden.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Was steht "im Hintergrund" nun in der Variable, wenn ein Objekt initialisiert wird?</p>
|
||||
<p>Antwort: Ein "Flag" sowie eine Speicherreferenz zum Objekt. Das Flag gibt hierbei an, ob der Wert direkt in der Variable "steckt" oder im Heap mittels der Speicheradresse gefunden werden kann.</p>
|
||||
<p>Als Entwickler hat man in JS keine Handhabe darüber, wo die Werte gespeichert werden. Diese Komplexität wird über die darunter liegende JavaScript-Engine abstrahiert.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Fassen wir zusammen: Komplexe Objekte werden im Heap allokiert, die Variable die den Wert hält ist eigentlich nur ein Pointer zur Speicheradresse im Heap.</p>
|
||||
<p>Ändern wir nun eine Eigenschaft im Objekt (Property), ändern wir den Wert im <strong>Heap</strong>. Die Adresse im Stack bleibt gleich.</p>
|
||||
<p>Und hier liegt der Punkt: Der Wert im Stack wird nicht modifiziert, entsprechend bleibt der Wert "konstant" und stellt keine Verletzung der <code>const</code> Bedingung aus.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Weitere Besonderheiten mit der Speicherbelegung von Objekten</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Wenn ein Objekt aus einem anderen Objekt generiert wird, erfolgt <strong>kein</strong> Deep-Copy.</p>
|
||||
<p>In der Realität geschieht ein <strong>copy-by-reference</strong>.</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = {};
|
||||
const otherObj = obj;
|
||||
|
||||
// true
|
||||
console.log(obj === otherObj);
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Nun ist wichtig zu beobachten, was passiert wenn wir das Objekt an einer beliegen Variable ändern:</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = {};
|
||||
const otherObj = obj;
|
||||
|
||||
obj.value = 42;
|
||||
|
||||
// 42
|
||||
console.log(otherObj.value);
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Durch diese beiden Beispiele wird nochmals eindeutig, dass wir bei der Handhabung von Objekten genau darauf achten müssen, was wir machen.</p>
|
||||
<p>Moderne Frameworks verwenden diese Konzepte für die eigene Datenhaltung. Hier kann es bei nichtbeachtung der "Regeln" zu ungewollten Problemen kommen.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Object-Spezifische Funktionen</h3>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Sollte es notwendig sein ein Objekt "read-only" zu machen, nutzen Sie <code>Object.freeze(objectToFreeze)</code></p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const myObject = { value: 5 };
|
||||
Object.freeze(myObject);
|
||||
|
||||
// Erzeugt einen Error
|
||||
myObject.value = 42;
|
||||
</code></pre>
|
||||
<p>Obwohl es Sinnvoll sein kann, wird <code>Object.freeze()</code> recht selten eingesetzt.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Objekte können auch ohne Probleme erweitert werden:</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = {
|
||||
value: 5,
|
||||
};
|
||||
|
||||
// Neue Property mit Namen "type"
|
||||
obj.type = "number";
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Sobald eine Property definiert ist, existiert sie im Objekt, auch wenn diese auf <code>undefined</code> gesetzt wird.</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = { value: 5, type: "number" };
|
||||
obj.type = undefined;
|
||||
|
||||
console.log(obj);
|
||||
// Object { value: 5, type: undefined };
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Soll eine Property wirklich entfernt werden, kann man dies mit dem <code>delete</code> keyword bewerkstelligen.</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = { value: 5, type: "number" };
|
||||
delete obj.type
|
||||
|
||||
console.log(obj);
|
||||
// Object { value: 5 };
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Wir haben die Möglichkeit, die keys, die values oder beide in ein Array zu konvertieren um darüber zu iterieren und Operationen auszuführen.</p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = { value: 5 };
|
||||
|
||||
// ['value']
|
||||
console.log(Object.keys(obj));
|
||||
|
||||
// [5]
|
||||
console.log(Object.values(obj));
|
||||
|
||||
// [['value', 5]];
|
||||
console.log(Object.entries(obj));
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Um zu prüfen, ob ein Objekt ein Property hat, nutzt man die Funktion <code>Object.hasOwn</code></p>
|
||||
<pre class="js"><code data-trim data-line-numbers is:raw>
|
||||
const obj = { value: 5 };
|
||||
|
||||
// true
|
||||
console.log(Object.hasOwn(obj, 'value'));
|
||||
// false
|
||||
console.log(Object.hasOwn(obj, 'other'));
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
</section>
|
|
@ -0,0 +1,3 @@
|
|||
<section>
|
||||
<h1>Komplexe Datentypen <br>(Objekte und Arrays)</h1>
|
||||
</section>
|
8
src/pages/slides/javascript/02-complex-datatypes.astro
Normal file
8
src/pages/slides/javascript/02-complex-datatypes.astro
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
import Reveal from '../../../layouts/Reveal.astro';
|
||||
import Slides from '../../../components/slides/javascript/02-complex-datatypes/index.astro';
|
||||
---
|
||||
|
||||
<Reveal title="JavaScript - Komplexe Datentypen">
|
||||
<Slides />
|
||||
</Reveal>
|
Loading…
Add table
Add a link
Reference in a new issue