Vorlesung 2
JavaScript Grundlagen

Die Konsole

Kontrollausgabe beim Entwickeln

Das console-Objekt, ursprünglich eingeführt durch das Firefox-Plugin Firebug, ermöglicht das Schreiben auf die Standardausgabe in JavaScript-Umgebungen...

Die verfügbaren Methoden des console-Objekts variieren je nach der spezifischen JavaScript-Umgebung...

MethodeBeschreibung
clear()Leert die Konsole
debug()Erwartet ein oder mehrere Objekte und gibt diese auf der Konsole aus.
error()Erwartet wie debug() ein oder mehrere Objekte und gibt diese als Fehler auf der Konsole aus. In Browsern wird innerhalb der Konsole oft ein Fehler-Icon neben der ausgegebenen Meldung dargestellt sowie der Fehler-Stack ausgegeben.
info()Hiermit werden die übergebenen Objekte als Info-Meldung auf die Konsole ausgegeben. Chrome beispielsweise gibt zusätzlich ein InfoIcon mit aus.
log()Die wohl am häufigsten verwendete Methode von console. Loggt die übergebenen Objekte auf die Konsole.
trace()Gibt den Stack-Trace, also den Methodenaufruf-Stack, auf die Konsole aus.
warn()Gibt die übergebenen Objekte als Warnung auf die Konsole aus. Auch hier wird in den meisten Browsern ein entsprechendes Icon neben der Meldung ausgegeben.

Dynamische Typisierung

JavaScript unterscheidet sich in mehreren Aspekten von statisch typisierten Sprachen wie Java oder C#. In statisch typisierten Sprachen sind die Typen von Variablen, Parametern und Objekteigenschaften zur Compile-Zeit bekannt und können zur Durchführung von Typüberprüfungen genutzt werden. Dies ermöglicht die frühzeitige Erkennung von typbedingten Fehlern bereits zur Compile-Zeit. In JavaScript hingegen ist die Typisierung vollständig dynamisch. Die Typen werden erst zur Laufzeit ermittelt, und es ist nicht erforderlich, Typen für Variablen anzugeben. Es gibt dennoch Typen in JavaScript, jedoch ist die Anzahl im Vergleich zu anderen Sprachen begrenzt und kann fast an einer Hand abgezählt werden. Dies bedeutet, dass JavaScript-Entwickler flexibel mit den zur Verfügung stehenden Typen umgehen können, jedoch auch sorgfältig auf Typfehler achten müssen, die erst zur Laufzeit auftreten können.

Variablen und Zugriff

In JavaScript gibt es verschiedene Arten von Variablen und unterschiedliche Möglichkeiten, auf sie zuzugreifen. Hier sind die wichtigsten Arten von Variablen und deren Zugriff in JavaScript:

Lokale Variablen (var, let, const)

var: Früher üblicher Weg, um Variablen zu deklarieren, jedoch weniger empfohlen. Lokale var-Variablen sind funktionsübergreifend sichtbar (nicht blockübergreifend).

let: Eingeführt in ECMAScript 6 (ES6), wird für blockscoped (blockübergreifende) Variablen verwendet. Sie sind nur in ihrem Block oder in verschachtelten Blöcken sichtbar.

const: Ähnlich wie let, erstellt aber Konstanten, deren Wert nach der Initialisierung nicht geändert werden kann.


function exampleFunction() {
    var localVar = 10;   // var ist funktionsübergreifend sichtbar
    let blockVar = 20;   // blockscoped mit let
    const constantVar = 30; // Konstante mit const

    console.log(localVar);
    console.log(blockVar);
    console.log(constantVar);
}

exampleFunction();

console.log(localVar); // Fehler: localVar ist nicht definiert
console.log(blockVar); // Fehler: blockVar ist nicht definiert
console.log(constantVar); // Fehler: constantVar ist nicht definiert

Globale Variablen

Globale Variablen sind außerhalb von Funktionen deklariert und können von überall im Code zugegriffen werden. Sie sollten sparsam verwendet werden, da sie das Risiko von Namenskonflikten erhöhen.


var globalVar = 42;

function accessGlobal() {
    console.log(globalVar);
}

accessGlobal(); // Ausgabe: 42

Objekt-Eigenschaften

Variablen können auch als Eigenschaften von JavaScript-Objekten gespeichert werden. Der Zugriff erfolgt über den Punktoperator oder den Bracket-Operator.


var person = {
    name: "Alice",
    age: 30
};
console.log(person.name); // Zugriff mit Punktoperator
console.log(person['age']); // Zugriff mit Bracket-Operator

Array-Elemente

In JavaScript können Variablen auch in Arrays gespeichert werden. Der Zugriff auf Array-Elemente erfolgt über den Index.


var fruits = ['Apple', 'Banana', 'Cherry'];

console.log(fruits[0]); // Zugriff auf das erste Element
console.log(fruits.length); // Länge des Arrays
                    

Wichtige Methoden von Arrays

MethodeBeschreibung
concat ()Hängt Elemente oder Arrays an ein bestehendes Array an.
filter()Filtert Elemente aus dem Array auf Basis eines in Form einer Funktion übergebenen Filterkriteriums.
forEach()Wendet eine übergebene Funktion auf jedes Element im Array an.
join()Wandelt ein Array in eine Zeichenkette um.
map()Bildet die Elemente eines Arrays auf Basis einer übergebenen Umwandlungsfunktion auf neue Elemente ab
pop()Entfernt das letzte Element eines Arrays.
push()Fügt ein neues Element am Ende des Arrays ein.
reduce ()Fasst die Elemente eines Arrays auf Basis einer übergebenen Funktion zu einem Wert zusammen.
reverse()Kehrt die Reihenfolge der Elemente im Array um.
shift()Entfernt das erste Element eines Arrays.
slice()Schneidet einzelne Elemente aus einem Array heraus.
splice()Fügt neue Elemente an beliebiger Position im Array hinzu.
sort ()Sortiert das Array, optional auf Basis einer übergebenen Vergleichsfunktion.
unshift()Fügt ein Element oder mehrere Elemente an den Anfang eines Arrays hinzu.

Funktionen als Variablen

In JavaScript können auch Funktionen als Variablen verwendet werden. Sie können direkt aufgerufen oder an andere Funktionen übergeben werden.


var add = function(a, b) {
    return a + b;
};
                    console.log(add(2, 3)); // Aufruf der Funktion

Closures

JavaScript unterstützt Closures, die es ermöglichen, auf Variablen aus umgebenden Funktionen zuzugreifen.


function outerFunction() {
    var outerVar = 'I am from outerFunction';
    
    function innerFunction() {
        console.log(outerVar);
    }
    
    return innerFunction;
}

var closureFunc = outerFunction();
closureFunc(); // Ausgabe: 'I am from outerFunction'
                    

Privater Zugriff

In JavaScript gibt es keine expliziten privaten Variablen oder Methoden auf klassische Weise wie in einigen anderen Programmiersprachen. Allerdings gibt es Techniken und Konventionen, um in JavaScript den Eindruck von Privatsphäre zu schaffen:

Closure: Eine gängige Technik zur Erzeugung von privaten Variablen in JavaScript ist die Verwendung von Closures. Indem Sie eine Funktion in einer anderen Funktion definieren, können Sie auf die Variablen der äußeren Funktion zugreifen, während diese Variablen von außen nicht sichtbar sind.


function createCounter() {
    let count = 0; // Private Variable
    return function() {
        count++;
        console.log(count);
    };
}

const counter = createCounter();
counter(); // Ausgabe: 1
counter(); // Ausgabe: 2
                    

Module Pattern: Das Modulmuster nutzt Closures, um private Variablen und Funktionen innerhalb eines Moduls zu verbergen und nur ausgewählten Teilen des Codes den Zugriff darauf zu ermöglichen. Dies wird oft verwendet, um private Mitglieder in JavaScript-Klassen zu erstellen.


const myModule = (function() {
    let privateVar = 'Ich bin privat';
    
    function privateFunction() {
        console.log('Private Funktion');
    }
    
    return {
        publicVar: 'Ich bin öffentlich',
        publicFunction: function() {
            console.log('Öffentliche Funktion');
            console.log(privateVar); // Zugriff auf private Variable
            privateFunction(); // Zugriff auf private Funktion
        }
    };
})();

console.log(myModule.publicVar); // Ausgabe: 'Ich bin öffentlich'
myModule.publicFunction(); // Ausgabe: 'Öffentliche Funktion' und 'Ich bin privat'
                    

Symbole: Mit ES6 wurden Symbole eingeführt, die es ermöglichen, private Mitglieder in Klassen zu erstellen. Symbole sind einzigartige Werte und können als Schlüssel für Objekteigenschaften verwendet werden.


const privateVarSymbol = Symbol('privateVar');

class MyClass {
    constructor() {
        this[privateVarSymbol] = 'Ich bin privat';
    }

    getPrivateVar() {
        return this[privateVarSymbol];
    }
}

const instance = new MyClass();
console.log(instance.getPrivateVar()); // Ausgabe: 'Ich bin privat'
                    

Es ist wichtig zu beachten, dass diese Techniken die Sichtbarkeit von Variablen und Funktionen eingeschränkt halten, aber sie sind nicht wirklich privat im Sinne einer starken Kapselung wie in einigen anderen Programmiersprachen. Entwickler sollten sich dieser Konzepte bewusst sein und sicherstellen, dass sie den Code in Übereinstimmung mit den Konventionen für Sichtbarkeit und Zugriff schreiben.

Null / Undefined

In JavaScript gibt es zwei unterschiedliche Werte, die ausdrücken, dass eine Variable keinen Wert zugewiesen hat: undefined und null.

undefined ist ein globaler Wert, der angibt, dass eine Variable nicht initialisiert wurde, auf nicht vorhandene Objekteigenschaften oder nicht übergebene Funktionsparameter verweist. Es zeigt auf die globale Variable. Funktionen, die keinen expliziten Rückgabewert haben, liefern standardmäßig undefined.

null hingegen ist ein Schlüsselwort und wird oft verwendet, um auszudrücken, dass eine Variable bewusst keinen Wert hat. In der Praxis werden beide Werte manchmal für denselben Zweck verwendet, nämlich um anzuzeigen, dass eine Variable keinen Wert enthält. Es wird jedoch empfohlen, den Wert undefined nicht explizit einer Variable zuzuweisen, sondern stattdessen null zu verwenden.

Die Verwendung von null anstelle von undefined kann dazu beitragen, die Absicht klarer auszudrücken, dass die Variable bewusst keinen Wert hat, anstatt dass sie einfach nicht initialisiert wurde.

Operatoren

Arithmetische Operatoren

  • +: Addition
  • -: Subtraktion
  • *: Multiplikation
  • /: Division
  • %: Modulo (Restwert nach Division)

Zuweisungsoperatoren

  • =: Zuweisung
  • +=: Addition und Zuweisung
  • -=: Subtraktion und Zuweisung
  • *=: Multiplikation und Zuweisung
  • /=: Division und Zuweisung
  • %=: Modulo und Zuweisung

Vergleichsoperatoren

  • ==: Gleich
  • !=: Ungleich
  • ===: Strikte Gleichheit (Wert und Typ)
  • !==: Strikte Ungleichheit (Wert und Typ)
  • >: Größer als
  • <: Kleiner als
  • >=: Größer oder gleich
  • <=: Kleiner oder gleich

Logische Operatoren

  • &&: Logisches UND (UND-Verknüpfung)
  • ||: Logisches ODER (ODER-Verknüpfung)
  • !: Logisches NICHT (Negation)

Inkrement- und Dekrementoperatoren

  • ++: Inkrement (Erhöhung um 1)
  • --: Dekrement (Verminderung um 1)

Ternärer Operator

  • condition ? expr1 : expr2: Kurzform einer bedingten (ternären) Anweisung

Weitere Operatoren

  • typeof: Gibt den Datentyp einer Variable zurück
  • instanceof: Überprüft, ob ein Objekt eine Instanz einer bestimmten Klasse oder eines Konstruktors ist
  • ,: Kommaoperator (Ausführung von Ausdrücken von links nach rechts und gibt den Wert des rechten Ausdrucks zurück)

Diese Operatoren sind grundlegend für die Durchführung von Berechnungen, Vergleichen, logischen Prüfungen und anderen Operationen in JavaScript. Sie werden in der Programmierung verwendet, um die Funktionalität von JavaScript-Anwendungen zu steuern und Daten zu verarbeiten.

Was sind Funktionen in JavaScript?

In JavaScript sind Funktionen eigenständige Codeblöcke, die eine spezifische Aufgabe ausführen können. Sie spielen eine zentrale Rolle in der JavaScript-Programmierung und ermöglichen die Organisation von Code in wiederverwendbare Einheiten. Funktionen können Parameter akzeptieren, Berechnungen durchführen und Werte zurückgeben. Sie sind ein grundlegendes Konzept in JavaScript und bieten die Möglichkeit zur Modularisierung und Strukturierung von Code.

Funktionen erstellen:

Funktionsausdrücke


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

Funktionsdeklarationen


function subtract(x, y) {
    return x - y;
}
                

Pfeilfunktionen


const multiply = (c, d) => c * d;
                    

Funktionen aufrufen

Um eine Funktion in JavaScript aufzurufen, verwenden Sie den Funktionsnamen gefolgt von Klammern (). Wenn die Funktion Parameter erwartet, geben Sie die Werte in den Klammern an.


const result = add(5, 3); // Aufruf der 'add'-Funktion mit den Argumenten 5 und 3
                

Parameter und Rückgabewerte

Parameter: Funktionen können Parameter akzeptieren, die als Eingabeinformationen dienen. Diese Parameter sind in den Klammern der Funktionsdeklaration oder des Funktionsausdrucks definiert.


function greet(name) {
    return "Hallo, "$"{name}!";
}
                    

Rückgabewerte: Funktionen können Werte mit dem return-Statement zurückgeben. Wenn keine return-Anweisung vorhanden ist oder sie leer ist, gibt die Funktion undefined zurück.


function multiply(x, y) {
    return x * y;
}
                

Funktionen als Werte

In JavaScript sind Funktionen sogenannte "First-Class-Citizens", was bedeutet, dass sie wie jede andere Variable behandelt werden können. Sie können Funktionen als Argumente an andere Funktionen übergeben, sie als Rückgabewerte von Funktionen verwenden und sie in Variablen speichern.


function operate(a, b, operation) {
    return operation(a, b);
}

const result = operate(5, 3, add); // Verwendung der 'add'-Funktion als Argument
                    

Anonyme Funktionen

Funktionen ohne Namen werden als "anonyme Funktionen" bezeichnet. Sie können direkt als Argumente an andere Funktionen übergeben werden.


const sum = function(x, y) {
    return x + y;
};

const result = sum(4, 2); // Aufruf der anonymen Funktion
                

Funktionen sind ein grundlegendes Konzept in JavaScript und spielen eine wesentliche Rolle bei der Strukturierung und Organisation von Code. Sie ermöglichen die Wiederverwendbarkeit von Code und die Durchführung von Aufgaben in JavaScript-Anwendungen.

Pfeilfunktionen

Pfeilfunktionen, auch als "Arrow Functions" bezeichnet, sind eine spezielle Art von Funktionen in JavaScript, die mit ES6 (ECMAScript 2015) eingeführt wurden. Sie bieten eine kürzere Syntax zum Definieren von Funktionen im Vergleich zu herkömmlichen Funktionsausdrücken oder Funktionsdeklarationen. Pfeilfunktionen sind besonders nützlich für einfache Funktionen, die eine klare und kurze Definition erlauben.

Hier sind einige wichtige Merkmale und Eigenschaften von Pfeilfunktionen:

Kompakte Syntax

Die Syntax von Pfeilfunktionen ist oft kürzer und einfacher als die von herkömmlichen Funktionen.

Beispiel einer herkömmlichen Funktion:


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

Entsprechende Pfeilfunktion:


const add = (a, b) => a + b;
                

Kein this-Binding

Pfeilfunktionen haben kein eigenes this-Binding. Sie erben das this von ihrer umgebenden (äußeren) Funktion oder vom globalen Kontext. Dies ist besonders nützlich in Callback-Funktionen oder in Funktionen innerhalb von Objekten, da Sie das this nicht explizit binden müssen.


const person = {
    name: 'Alice',
    sayHello: function() {
        console.log("Hallo, mein Name ist "$"{this.name}");
    }
};

// Mit Pfeilfunktion:
const person = {
    name: 'Alice',
    sayHello: () => {
        console.log("Hallo, mein Name ist "$"{this.name}");
    }
};
                    

Kein arguments-Objekt

Pfeilfunktionen haben kein eigenes arguments-Objekt. Wenn Sie Zugriff auf die Argumente einer Funktion benötigen, sollten Sie herkömmliche Funktionen verwenden.


function traditionalFunction() {
    console.log(arguments);
}

const arrowFunction = () => {
    console.log(arguments); // Fehler: 'arguments' ist in Pfeilfunktionen nicht definiert
}
                

Kein new-Operator

Pfeilfunktionen können nicht als Konstruktoren verwendet werden. Sie können keine Instanzen von Objekten erstellen.


const ConstructorFunc = () => {}; // Fehler: Pfeilfunktionen können nicht als Konstruktoren verwendet werden
                    

Kurze Einzeiler

Pfeilfunktionen eignen sich gut für kurze Einzeiler-Funktionen. Wenn Ihre Funktion mehrere Anweisungen erfordert, sollten Sie herkömmliche Funktionen verwenden.


const isEven = (num) => num % 2 === 0; // Kurzer Einzeiler
                

Pfeilfunktionen sind eine praktische Ergänzung zu JavaScript, insbesondere für kurze und einfache Funktionen, bei denen eine kompakte Syntax und das Verhalten des this-Wertes ohne Bindung erforderlich sind. Sie haben jedoch bestimmte Einschränkungen und sollten sorgfältig ausgewählt werden, abhängig von den Anforderungen Ihrer Anwendung.

Higher-Order-Functions

Higher-Order-Functions (HOC) sind ein Konzept in der funktionellen Programmierung und in vielen modernen Programmiersprachen, einschließlich JavaScript. Eine Higher-Order-Function ist im Wesentlichen eine Funktion, die eine andere Funktion als Argument akzeptiert und/oder eine Funktion zurückgibt. Dies macht sie zu Funktionen, die auf Funktionen wirken, und erweitert die Möglichkeiten der Funktionen in der Programmierung erheblich.

Funktionen als Argumente

HOCs können andere Funktionen als Argumente akzeptieren. Dies ermöglicht es, Funktionen zu parametrisieren und die Funktionalität dynamisch zu gestalten.


function applyOperation(operation, x, y) {
    return operation(x, y);
}

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

function subtract(a, b) {
    return a - b;
}

const result = applyOperation(add, 5, 3); // Verwendung von 'add' als Argument
                    

Funktionen als Rückgabewerte

HOCs können auch Funktionen zurückgeben. Dies ermöglicht die Erstellung von Fabriken für Funktionen oder die Implementierung von Closures.


function createMultiplier(factor) {
    return function(x) {
        return x * factor;
    };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

const result1 = double(4); // Ergebnis: 8
const result2 = triple(5); // Ergebnis: 15
                

Abstraktion und Wiederverwendbarkeit

HOCs fördern die Abstraktion von Funktionalität und die Wiederverwendbarkeit von Code. Sie ermöglichen es, allgemeine Operationen auf Funktionen anzuwenden, ohne den Kerncode der Funktionen zu ändern.

Funktionen als Daten

In der funktionalen Programmierung werden Funktionen oft wie Daten behandelt. Dies ermöglicht es, Funktionen in Arrays oder Objekten zu speichern und sie dynamisch zu manipulieren.


const operations = {
    add: (a, b) => a + b,
    subtract: (a, b) => a - b,
};

const operationName = 'add';
const result = operations[operationName](5, 3); // Verwendung von 'add' aus dem Objekt
                    

Higher-Order-Functions sind ein leistungsstarkes Konzept in der funktionalen Programmierung und in modernen JavaScript-Anwendungen. Sie fördern die Flexibilität und Abstraktion von Code und ermöglichen es, komplexe Operationen auf Funktionen anzuwenden. Dies ist besonders nützlich für Aufgaben wie das Filtern von Arrays, das Mappen von Werten und das Verketten von Funktionen, um komplexe Aufgaben zu erfüllen.