JavaScript Anfänger

Funktionen Grundlagen in JavaScript

Funktionen Grundlagen

Funktionen sind wiederverwendbare Code-Blöcke. Sie sind eines der wichtigsten Konzepte in JavaScript und machen deinen Code organisiert, lesbar und wartbar.

Warum Funktionen?

Ohne Funktionen:

// Begrüßung für Max
console.log("Hallo Max!");
console.log("Willkommen auf unserer Seite!");
console.log("---");

// Begrüßung für Anna
console.log("Hallo Anna!");
console.log("Willkommen auf unserer Seite!");
console.log("---");

// Begrüßung für Tom
console.log("Hallo Tom!");
console.log("Willkommen auf unserer Seite!");
console.log("---");

Mit Funktionen:

function greet(name) {
    console.log(`Hallo ${name}!`);
    console.log("Willkommen auf unserer Seite!");
    console.log("---");
}

greet("Max");
greet("Anna");
greet("Tom");

Vorteile:

  • ✅ Weniger Wiederholung (DRY - Don’t Repeat Yourself)
  • ✅ Leichter zu ändern (nur an einer Stelle)
  • ✅ Besser lesbar
  • ✅ Testbar

Funktionen deklarieren

Function Declaration

function sayHello() {
    console.log("Hallo!");
}

// Aufrufen
sayHello(); // "Hallo!"

Function Expression

const sayHello = function() {
    console.log("Hallo!");
};

sayHello();

Arrow Function (Modern!)

const sayHello = () => {
    console.log("Hallo!");
};

// Kurzform bei einer Zeile
const sayHi = () => console.log("Hi!");

sayHello();
sayHi();

Parameter und Argumente

Parameter sind Eingaben für deine Funktion:

function greet(name) {  // "name" ist der Parameter
    console.log(`Hallo, ${name}!`);
}

greet("Max");    // "Max" ist das Argument
greet("Anna");

Mehrere Parameter

function createUser(name, age, city) {
    console.log(`${name}, ${age} Jahre, wohnt in ${city}`);
}

createUser("Max", 25, "Berlin");
// "Max, 25 Jahre, wohnt in Berlin"

Default-Parameter

function greet(name = "Gast") {
    console.log(`Hallo, ${name}!`);
}

greet();        // "Hallo, Gast!"
greet("Max");   // "Hallo, Max!"

// Komplexeres Beispiel
function createConfig(options = {}) {
    const config = {
        theme: options.theme || "light",
        language: options.language || "de",
        debug: options.debug ?? false
    };
    return config;
}

createConfig();                        // { theme: "light", language: "de", debug: false }
createConfig({ theme: "dark" });       // { theme: "dark", language: "de", debug: false }

Rest-Parameter ...

Sammelt beliebig viele Argumente:

function sum(...numbers) {
    let total = 0;
    for (const num of numbers) {
        total += num;
    }
    return total;
}

console.log(sum(1, 2));           // 3
console.log(sum(1, 2, 3, 4, 5));  // 15

// Mit normalen Parametern kombinieren
function greetAll(greeting, ...names) {
    for (const name of names) {
        console.log(`${greeting}, ${name}!`);
    }
}

greetAll("Hallo", "Max", "Anna", "Tom");
// "Hallo, Max!"
// "Hallo, Anna!"
// "Hallo, Tom!"

Rückgabewerte mit return

Funktionen können Werte zurückgeben:

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

const result = add(5, 3);
console.log(result);  // 8

// In Berechnungen verwenden
const total = add(10, 20) + add(5, 5);
console.log(total);  // 40

Frühe Returns

function divide(a, b) {
    if (b === 0) {
        return "Fehler: Division durch 0!";  // Früher Exit
    }
    return a / b;
}

console.log(divide(10, 2));  // 5
console.log(divide(10, 0));  // "Fehler: Division durch 0!"

Mehrere Werte zurückgeben

// Mit Object
function getUser() {
    return {
        name: "Max",
        age: 25,
        city: "Berlin"
    };
}

const user = getUser();
console.log(user.name);  // "Max"

// Mit Destructuring
const { name, age } = getUser();
console.log(name, age);  // "Max" 25

// Mit Array
function getMinMax(numbers) {
    return [Math.min(...numbers), Math.max(...numbers)];
}

const [min, max] = getMinMax([3, 1, 4, 1, 5, 9]);
console.log(min, max);  // 1 9

Arrow Functions im Detail

Arrow Functions sind die moderne Art, Funktionen zu schreiben:

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

// Arrow Function
const add = (a, b) => {
    return a + b;
};

// Kurzform (implicit return)
const add = (a, b) => a + b;

// Ein Parameter? Klammern optional
const double = x => x * 2;

// Kein Parameter? Leere Klammern
const getRandom = () => Math.random();

Wann welche Form?

// ✅ Einzeiler - Kurzform
const square = x => x * x;
const isEven = n => n % 2 === 0;
const greet = name => `Hallo, ${name}!`;

// ✅ Mehrere Zeilen - Mit Block
const processUser = (user) => {
    const fullName = `${user.firstName} ${user.lastName}`;
    const greeting = `Willkommen, ${fullName}!`;
    return greeting;
};

// ✅ Object zurückgeben - Klammern um Object!
const createUser = (name, age) => ({
    name,
    age,
    createdAt: new Date()
});

Scope (Gültigkeitsbereich)

Variablen haben einen Gültigkeitsbereich:

Global Scope

const globalVar = "Ich bin überall verfügbar";

function test() {
    console.log(globalVar);  // ✅ Funktioniert
}

test();
console.log(globalVar);  // ✅ Funktioniert

Function Scope

function test() {
    const localVar = "Nur in dieser Funktion";
    console.log(localVar);  // ✅ Funktioniert
}

test();
console.log(localVar);  // ❌ ReferenceError!

Block Scope (let/const)

if (true) {
    const blockVar = "Nur in diesem Block";
    let anotherBlock = "Auch nur hier";
    console.log(blockVar);  // ✅ Funktioniert
}

console.log(blockVar);  // ❌ ReferenceError!

// Deshalb kein var verwenden!
if (true) {
    var leakyVar = "Ich lecke raus!";
}
console.log(leakyVar);  // ⚠️ Funktioniert (schlecht!)

Scope Chain

Funktionen können auf äußere Variablen zugreifen:

const outer = "Außen";

function outerFunction() {
    const middle = "Mitte";

    function innerFunction() {
        const inner = "Innen";

        console.log(inner);   // ✅ "Innen"
        console.log(middle);  // ✅ "Mitte"
        console.log(outer);   // ✅ "Außen"
    }

    innerFunction();
}

outerFunction();

Funktionen als Werte

In JavaScript sind Funktionen First-Class Citizens - sie können wie normale Werte behandelt werden:

In Variablen speichern

const myFunc = function() {
    console.log("Hallo!");
};

const anotherRef = myFunc;  // Referenz kopieren
anotherRef();  // "Hallo!"

Als Parameter übergeben

function doSomething(callback) {
    console.log("Vor dem Callback");
    callback();
    console.log("Nach dem Callback");
}

doSomething(() => console.log("Ich bin der Callback!"));
// "Vor dem Callback"
// "Ich bin der Callback!"
// "Nach dem Callback"

Aus Funktionen zurückgeben

function createMultiplier(factor) {
    return (number) => number * factor;
}

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

console.log(double(5));  // 10
console.log(triple(5));  // 15

Praktische Beispiele

Validierungs-Funktionen

const isEmail = (email) => {
    return email.includes("@") && email.includes(".");
};

const isStrongPassword = (password) => {
    const minLength = password.length >= 8;
    const hasNumber = /\d/.test(password);
    const hasUpper = /[A-Z]/.test(password);
    return minLength && hasNumber && hasUpper;
};

const isEmpty = (value) => {
    return value === null || value === undefined || value === "";
};

// Verwendung
if (isEmpty(username)) {
    console.log("Username erforderlich");
}

if (!isEmail(email)) {
    console.log("Ungültige E-Mail");
}

if (!isStrongPassword(password)) {
    console.log("Passwort zu schwach");
}

Array-Helfer

const sum = (numbers) => numbers.reduce((a, b) => a + b, 0);
const average = (numbers) => sum(numbers) / numbers.length;
const max = (numbers) => Math.max(...numbers);
const min = (numbers) => Math.min(...numbers);

const grades = [85, 90, 78, 92, 88];

console.log(`Summe: ${sum(grades)}`);       // 433
console.log(`Durchschnitt: ${average(grades)}`); // 86.6
console.log(`Beste Note: ${max(grades)}`);  // 92
console.log(`Schlechteste: ${min(grades)}`); // 78

Preis-Formatter

function formatPrice(amount, currency = "EUR", locale = "de-DE") {
    return new Intl.NumberFormat(locale, {
        style: "currency",
        currency: currency
    }).format(amount);
}

console.log(formatPrice(1234.56));           // "1.234,56 €"
console.log(formatPrice(1234.56, "USD", "en-US")); // "$1,234.56"

Event-Handler Factory

function createClickHandler(message) {
    return function(event) {
        console.log(message);
        console.log("Geklickt auf:", event.target);
    };
}

// Verwendung
button1.onclick = createClickHandler("Button 1 wurde geklickt");
button2.onclick = createClickHandler("Button 2 wurde geklickt");

Best Practices

1. Eine Funktion, eine Aufgabe

// ❌ Macht zu viel
function processUser(user) {
    // Validieren
    // Speichern
    // E-Mail senden
    // Logs schreiben
}

// ✅ Aufgeteilt
function validateUser(user) { /* ... */ }
function saveUser(user) { /* ... */ }
function sendWelcomeEmail(user) { /* ... */ }
function logUserCreation(user) { /* ... */ }

2. Aussagekräftige Namen

// ❌ Unklar
function proc(d) { }
function handle(x, y) { }

// ✅ Klar
function processOrder(orderData) { }
function calculateTax(price, taxRate) { }

3. Keine Seiteneffekte

// ❌ Ändert globalen State
let total = 0;
function addToTotal(amount) {
    total += amount;  // Seiteneffekt!
}

// ✅ Gibt neuen Wert zurück
function add(a, b) {
    return a + b;  // Keine Seiteneffekte
}

4. Wenige Parameter

// ❌ Zu viele Parameter
function createUser(name, age, city, email, phone, role) { }

// ✅ Options-Object
function createUser(options) {
    const { name, age, city, email, phone, role } = options;
}

// Oder mit Destructuring
function createUser({ name, age, city = "Berlin", email, phone = null, role = "user" }) {
    // ...
}

Zusammenfassung

KonzeptBeispiel
Function Declarationfunction name() {}
Function Expressionconst name = function() {}
Arrow Functionconst name = () => {}
Parameterfunction greet(name) {}
Default-Parameterfunction greet(name = "Gast") {}
Rest-Parameterfunction sum(...nums) {}
Returnreturn value;
ScopeGlobal, Function, Block

💡 Merke: Gute Funktionen sind kurz, machen eine Sache und haben aussagekräftige Namen. Nutze Arrow Functions für kurze Callbacks und normale Funktionen für komplexere Logik!