Objekte

Klassen und objektorientierte Programmierung (OOP)

Selbstverständlich könnte man ein Programm mit lauter einzelnen Variablen, Arrays und losen Funktionen schreiben. Bei komplexeren Anwendungen führt das jedoch schnell zu unüberschaubarem „Spaghetti-Code“. Um Ordnung, Struktur und Wiederverwendbarkeit in Software zu bringen, wurde die objektorientierte Programmierung (OOP) entwickelt.

Das Design einer OOP-Software besteht aus einer Anzahl miteinander kommunizierender und interagierender Objekte.

Die Auto-Metapher: > Stell dir ein Auto vor. Es ist eine komplexe Maschine, die aus vielen eigenständigen Bauteilen besteht (Motor, Bremsen, Elektronik). Jedes Bauteil funktioniert für sich (Verkapselung), verbirgt seine innere Komplexität (Abstraktion) und reagiert auf Signale – zum Beispiel, wenn du das Gaspedal drückst. In der OOP bauen wir Software genau nach diesem Prinzip: aus unabhängigen, intelligenten Bausteinen.

Von der Blaupause zum Objekt

Um ein Objekt zu erzeugen, benötigen wir einen Bauplan. Diesen Bauplan nennen wir Klasse. Aus einer Klasse können wir dann beliebig viele konkrete Ausprägungen – sogenannte Instanzen (Objekte) – erstellen.

In JavaScript nutzen wir dafür heute standardmäßig das Schlüsselwort class (eingeführt mit ES6) und den Befehl new zur Initialisierung:

JavaScript
// Die Blaupause (Klasse)
class Auto {    constructor(marke) {
this.marke = marke; // Eine Eigenschaft
}  }
// Die Instanziierung (Das konkrete Objekt)
const meinAuto = new Auto("Tesla");  

Die 3 Grundpfeiler eines Objekts

Jedes Objekt in der OOP wird durch drei wesentliche Merkmale definiert:

  1. Eigenschaften (Properties): Die Daten oder der Zustand des Objekts (z. B. farbe = "rot", geschwindigkeit = 50).

  2. Methoden (Methods): Die Fähigkeiten oder das Verhalten des Objekts – im Grunde Funktionen, die an das Objekt gebunden sind (z. B. bremsen(), beschleunigen()).

  3. Ereignisse (Events): Signale, auf die das Objekt reagieren kann oder die es selbst aussendet (z. B. motorGestartet).

Wichtige Kernbegriffe der OOP kurz erklärt

In der folgenden Grafik sieht man einige Objekte. Der Zustand von Objekten wird über die Eigenschaften und die Verbindung zu anderen Objekten definiert. Das Verhalten von Objekten wird über die Methoden definiert. Der Zustand von ShoppingCart wird über Anzahl und Art der  items definiert.   Mit seinen Methoden kann man items hinzufügen entfernen oder alle löschen.  

Objekte

Objekt-Literal & Klassen

Während du ein Objekt-Literal {} nutzt, um einmalige Daten schnell und unkompliziert an einem Ort zu bündeln (quasi als einzelnes Notizblatt), verwendest du eine Klasse, wenn du eine wiederverwendbare Schablone (eine Fabrik) benötigst, um beliebig viele Objekte derselben Art mit eigenen Funktionen zu erzeugen.

Objekt-Literal

„Hinweis: In JavaScript ist fast alles ein Objekt. Wenn wir ein Objekt direkt mit geschweiften Klammern {...} im Code hinschreiben, sprechen wir spezifisch von einem Objekt-Literal. Das ist die einfachste Form, um Daten zu strukturieren.“

Objekte kann man auf verschiedene Arten herstellen. Im folgenden wird ein Objekt mit der Literal Schreibweise erzeugt.

Objekte haben eine starke Ähnlichkeit mit Arrays. Es wird jedoch anstatt eines Index ein String benutzt. Diesen nennt man auch Key, Schlüssel oder Eigenschaft. Die Elemente, auf die sie verweisen, nennt man Werte.

let trex = {
"beine" : 2,
"laenge" : 6,
"nahrung" : "Fleischfresser",
"ruf" : () => alert("rrrooaaarrr")
}
Schlüssel   Wert
"beine" : 2
"laenge" : 6
"nahrung" : "Fleischfresser"
"ruf" : ()=>alert("roar")

Wir haben es hier mit Schlüssel-Werte- Paaren zu tun. Während Arrays in der Regel eine Reihe gleichartiger Werte enthält, so haben Objekte in der Regel einzelne Elemente mit Eigenschaften oder Attributen. Ein Beispiel verdeutlicht den Unterschied. Ein Array dinos enthält die Namen verschiedener Dinosaurier. Ein Objekt könnte die verschiedenen Eigenschaften und Attribute eines einzelnen Dinosauriers enthalten, wie Größe, Gewicht, Anzahl der Beine etc.

Hier wird ein Objekt namens trex erstellt. Diese bekommt 3 Schlüssel- Werte- Paare. Im Gegensatz zu Arrays, werden Objekte in geschweiften Klammern anstatt in eckigen Klammern gesetzt. Alles was zwischen den geschweiften Klammern steht wird Objektliteral genannt. Literal bedeutet, der gesamte Wert wird in einem Schritt aufgeschrieben und nicht nacheinander aufgebaut.

Der Schlüssel ist immer ein String. Er muss allerdings nicht in Anführungsstrichen geschrieben sein. Wenn man ihn jedoch ohne Anführungszeichen schreibt, muss man diesselben Regeln wie bei Variablennamen beachten. Schreibt man den Schlüssel in Anführungsstrichen sind beispielsweise auch Leerzeichen erlaubt.

let trex = {
  beine : 2,
  laenge : 6,
  nahrung : "Fleischfresser",
  ruf : () => alert("rrroooaarrr")
}

Auf Objekte zugreifen:

Man kann genau wie bei Arrays über eckige Klammern auf die Objektwerte zugreifen, die Eigenschaft sollte in Anführungszeichen stehen.

trex["beine"]

Eine andere Möglichkeit ist der Zugriff über Punktsyntax:

trex.beine

Die Punktsyntax kann man nur nutzen, wenn der Schlüssel nicht in Anführungszeichen steht, oder wenn der Schlüssel keine verbotenen Sonderzeichen und/ oder Leerzeichen enthält.

Greift man auf einen Schlüssel zu, den es nicht gibt, wird der Wert undefined geliefert

Object.keys() / Zugriff auf alle Schlüssel

Object.keys(meinObjekt) liefert ein Array mit allen Schlüsseln.
Eine andere Möglichkeit alle Eigenschaften zu durchlaufen ist die for-in-Schleife.

Beispiel
  let dino = {art: "T-Rex", beine : 2, food: 'meat'}
  Object.keys(dino);  //4['art', 'beine', 'food'] 

Die Schlüssel in Objekten haben keine festgelegte Reihenfolge, wie das bei einem Array der Fall ist. In unserem Beispiel ist "beine" nicht unbedingt das erste Element.

In folgendem Beispiel werden die Eigenschaften und deren Werte angezeigt. Voraussetzung ist ein HTML Element mit der id="output":

let dino = {art:"T-Rex", beine: 5, food:"meat"}
let ausgabe = document.getElementById("output");
let dino = { art: "T-Rex", beine: 5, food: "meat" };
let dinoAr = Object.values(dino);

let dinoKeys = Object.keys(dino);
   
for(let i= 0; i < dinoKeys.length; i++){
    let key = dinoKeys[i];  
    anzeige.innerHTML += `${key} : ${dino[key]}`;
}

Object.values() greift auf alle Elemente zu und macht daraus ein Array

let dino = { art: "T-Rex", beine: 5, food: "meat" };
let dinoAr = Object.values(dino);
conosle.log(dinoAr) // ["T-Rex", 5,  "meat"]

Object.entries() wandelt ein Objekt in ein zweidimensionales Array um

let dino = { art: "T-Rex", beine: 5, food: "meat" };
let dinoArr = Object.entries(dino);
console.log(dinoArr); //[ [ 'art', 'T-Rex' ], [ 'beine', 5 ], [ 'food', 'meat' ] ]
 

for-in Schleife / Zugriff auf alle Elemente

Beispiel
Siehe dazu auch das Thema for-in-Schleife. Mit einer for-in-Schleife ist der Zugriff auf alle Elemente eines Objekts einfacher als mit Object.keys().

let dino = {art:"T-Rex", beine: 5, food:"meat"}
let ausgabe = document.getElementById("output");
  for(let prop in  dino){
    ausgabe.innerHTML += prop +": "+ dino[prop] +"<br>";
}

Werte zu Objekten hinzufügen

Man kann auch Schlüssel-Werte Paare im Nachhinein hinzufügen. Hier wird zuerst ein leeres Objekt mit geschweiften Klammern erstellt, dann werden die Schlüssel-Werte Paare hinzugefügt.

Eine Möglichkeit

let trex = {};  
  trex["beine"] = 2;
  trex["laenge"]= 6;
  trex["nahrung"] = "Fleischfresser";
  

Punktsyntax

let trex = {};  
  trex.beine = 2;
  trex.laenge= 6;
  trex.nahrung = "Fleischfresser";
  

Arrays und Objekte kombinieren

Man kann einem Array als Wert ein weiteres Array hinzufügen. Oder die Werte eines Arrays bestehen aus lauter Objekten. Damit erzeugt man datenbankähnliche Strukturen.

let dinosaurier = [
{ name: "Tyrannosaurus Rex", beine: 2, laenge : 6, nahrung: "andere Saurierer"},
{ name: "Stegosaurus", beine: 4, laenge: 8, nahrung: "Obst und Gemüse"},
{ name: "Brontosaurus", beine: 4, lange: 15, nahrung: "Blätter"}
];

Wir haben hier ein Array dinosaurier. Die Werte werden in eckigen Klammern eingefügt und mit Komma getrennt. Die Werte sind Objekte, welche in geschweiften Klammern eingefügt werden.

Man kann auch nachträglich Objekte hinzufügen:

let dinosaurier = [];
dinosaurier[0] = {};	
dinosaurier[0]["beine"] =  2;
dinosaurier[0]["name"] = "T-Rex";

Zugriff

Der Zugriff auf einen einzelnen Dino geschieht über den index. Alle Eigenschaften des ersten Dinos werden folgendermaßen geliefert:

dinosaurier[0]

dinosaurier[0]["name"] liefert "Tyrannosaurus Rex"

andere Möglichkeit Punktsyntax

dinosaurier[0].name

Kurzschreibweise wenn Variablennamen und Keys gleich sind

Die "Property Shorthand" (Eigenschafts-Kurzschreibweise) ist ein echtes Komfort-Feature aus ES6, das man im Alltag ständig nutzt, weil es unglaublich viel Tipparbeit spart. Wenn du in JavaScript ein Objekt erstellst (ein Objekt-Literal), musst du ja immer Paare aus Schlüssel (Key) und Wert (Value) angeben, getrennt durch einen Doppelpunkt: schluessel: wert.

Sehr oft kommt es vor, dass der Wert aus einer Variable kommt, die exakt genauso heißt wie der Schlüssel im Objekt.

Das klassische Problem (vor ES6)

Nehmen wir an, du hast zwei Variablen und möchtest daraus ein Daten-Objekt für einen User bauen:

Javascript
const name = "Willi";
const alter = 42;

// Altmodisch: Du musst jeden Namen doppelt schreiben
const user = {
name: name, // Schlüssel ist 'name', Wert kommt aus Variable 'name'
alter: alter // Schlüssel ist 'alter', Wert kommt aus Variable 'alter'
};

Die moderene Lösung (Kürzere Syntax)

Da dieses "Doppelt-Schreiben" extrem redundant ist, hat JavaScript folgende Regel eingeführt: Wenn der Schlüssel im Objekt und der Name der Variablen identisch sind, kannst du den Doppelpunkt und den Wert einfach weglassen.

Javascript kapiert von alleine was gemeint ist:

const name = "Willi";
const alter = 42;

// Modern und kurz:
const user = {
name, // Macht im Hintergrund automatisch: name: name
alter // Macht im Hintergrund automatisch: alter: alter
};

console.log(user); // { name: "Willi", alter: 42 }

Ein weiteres Praxisbeispiel. In dieser Funktion wird ein Objekt zurück gegeben.

function berechne(zahl) {
const quadrat = zahl * zahl;
const hälfte = zahl / 2;

// Dank der Erweiterung kannst du das Objekt jetzt so zurückgeben:
return {
quadrat,
hälfte
};
}
Werte mit Destructing abholen
let { quadrat, hälfte } = berechne(4);
console.log(hälfte);
console.log(quadrat);

Javascript Tipps