Node.js-Funktionen

Eine Funktion ist ein wiederverwendbarer Codeblock, der verwendet wird, um eine bestimmte Aufgabe auszuführen.

In Node.js sind Funktionen eine der Kernkomponenten von JavaScript und die grundlegenden Bausteine von Anwendungen.

Node.js erbt alle Funktionsmerkmale von JavaScript, und sie spielen eine wichtige Rolle in seinem asynchronen Programmiermodell.

In JavaScript kann eine Funktion als Argument an eine andere Funktion übergeben werden. Wir können eine Funktion zuerst definieren und dann übergeben oder die Funktion direkt dort definieren, wo das Argument übergeben wird.

Bedeutung von Funktionen

  • Wiederverwendung von Code: Vermeiden Sie, dieselbe Logik wiederholt neu zu schreiben
  • Modularität: Zerlegen Sie komplexe Probleme in kleine Funktionen
  • Wartbarkeit: Erleichtert das Debuggen und Ändern unabhängiger funktionaler Einheiten

Funktionsdeklaration

Verwenden Sie dasfunctionSchlüsselwort, um eine Funktion zu deklarieren.

function greet(name) {
    console.log(`Hello, ${name}!`);
}

Funktionsausdruck

Weisen Sie einer Variablen eine Funktion zu.

const greet = function(name) {
    console.log(`Hello, ${name}!`);
};

Pfeilfunktionen

Kompakte Funktionsausdrücke, die mit ES6 eingeführt wurden.

const greet = (name) => {
    console.log(`Hello, ${name}!`);
};

// 单行箭头函数
const greet = name => console.log(`Hello, ${name}!`);

Arten von Funktionen

1. Reguläre Funktionen

Die gebräuchlichste Form einer Funktion, die Parameter und Rückgabewerte haben kann.

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

2. Anonyme Funktionen

Funktionen ohne Namen, die normalerweise als Argumente an andere Funktionen übergeben werden.

setTimeout(function() {
    console.log('This is an anonymous function.');
}, 1000);

3. Callback-Funktionen

Wird als Argument an eine andere Funktion übergeben und nach Abschluss einer bestimmten Operation aufgerufen.

function fetchData(callback) {
    setTimeout(() => {
        const data = 'Some data';
        callback(data);
    }, 1000);
}

fetchData((data) => {
    console.log(data);
});

Asynchrone Funktionen

Von Callbacks zu Promises.

Beispiel

function readFilePromise(path) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, 'utf8', (err, data) => {
      if (err) reject(err);
      else resolve(data);
    });
  });
}

Verwende die Schlüsselwörter async und await, um asynchrone Operationen zu behandeln.

Beispiel

async function fetchUser(id) {
    try {
        const response = await fetch(`https://api.example.com/users/${id}`);
        const user = await response.json();
        return user;
    } catch (error) {
        console.error('Fehler beim Abrufen des Benutzers:', error);
    }
}

fetchUser(1).then(user => console.log(user));

Vergleich von Call-Methoden

Call-Methode Beispiel Eigenschaften
Direkter Aufruf greet('Alice') Die gebräuchlichste Art
Aufruf als Methode obj.method() this verweist auf das aufrufende Objekt
Konstruktoraufruf new Constructor() Erzeugt eine neue Instanz
Indirekter Aufruf greet.call(null, 'Bob') Kann die this-Bindung ändern

Erweiterte Nutzung

1. Closures

Eine Closure ist eine Funktion, die sich an ihren lexikalischen Scope erinnern und auf ihn zugreifen kann, selbst wenn sie außerhalb dieses lexikalischen Scopes ausgeführt wird.

Beispiel

function createCounter() {
    let count = 0;
    return function() {
        count++;
        return count;
    };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2

2. Funktionen höherer Ordnung

Funktionen, die Funktionen als Argumente akzeptieren oder Funktionen zurückgeben.

Beispiel

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

const sum = applyOperation(5, 3, (x, y) => x + y);
const product = applyOperation(5, 3, (x, y) => x * y);

console.log(sum); // 8
console.log(product); // 15

Umgang mit Funktionsparametern

Standardparameter

Standardwerte für Parameter zum Zeitpunkt der Funktionsdeklaration bereitstellen.

function greet(name = 'Guest') {
    console.log(`Hello, ${name}!`);
}

greet(); // Hello, Guest!
greet('Alice'); // Hello, Alice!

Rest-Parameter

Ermöglicht es, eine unbestimmte Anzahl von Argumenten als Array darzustellen.

Beispiel

function sum(...numbers) {
    return numbers.reduce((acc, num) => acc + num, 0);
}

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

Destrukturierte Parameter

Extrahiert Daten aus Objekten oder Arrays und weist sie einem Array zu.

Beispiel

function getUserInfo({ name, age }) {
    console.log(`Name: ${name}, Alter: ${age}`);
}

const user = { name: 'Alice', age: 30 };
getUserInfo(user); // Name: Alice, Alter: 30

Beispiel

Einzelverantwortlichkeit von Funktionen:Jede Funktion sollte nur eine Sache tun, was das Testen und die Wartung erleichtert.

Beispiel

function calculateArea(width, height) {
    return width * height;
}

Globale Variablen vermeiden:Minimieren Sie die Verwendung globaler Variablen; verwenden Sie stattdessen lokale Variablen und Funktionsparameter.

Beispiel

function calculateTotal(items) {
    let total = 0;
    for (const item of items) {
        total += item.price * item.quantity;
    }
    return total;
}

Arrow-Funktionen verwenden:Arrow-Funktionen sind prägnant und klar, besonders beim Umgang mit Callback-Funktionen.

Beispiel

const users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' }
];

const names = users.map(user => user.name);
console.log(names); // ['Alice', 'Bob']

Fehlerbehandlung:Verwenden Sie try...catch-Anweisungen, um Fehler zu behandeln, die ausgelöst werden können.

Beispiel

async function fetchUser(id) {
    try {
        const response = await fetch(`https://api.example.com/users/${id}`);
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        const user = await response.json();
        return user;
    } catch (error) {
        console.error('Fehler beim Abrufen des Benutzers:', error);
    }
}

Funktionen als Parameter:Verwenden Sie eine Funktion als Argument.

Beispiel

function say(word) {
  console.log(word);
}

function execute(someFunction, value) {
  someFunction(value);
}

execute(say, "Hello");

Im obigen Code übergeben wir die Funktion say als erstes Argument der Funktion execute. Was hier übergeben wird, ist nicht der Rückgabewert von say, sondern say selbst!

Dadurch wird say zur lokalen Variable someFunction innerhalb von execute, und execute kann die Funktion say verwenden, indem es someFunction() aufruft (mit Klammern).

Natürlich kann execute, da say einen Parameter hat, beim Aufruf von someFunction ein solches Argument übergeben.

Anonyme Funktionen:Wir können eine Funktion als Variable übergeben. Aber wir müssen nicht den Umweg über „zuerst definieren, dann übergeben“ gehen; wir können die Funktion direkt innerhalb der Klammern einer anderen Funktion definieren und übergeben:

Beispiel

function execute(someFunction, value) {
  someFunction(value);
}

execute(function(word){ console.log(word) }, "Hello");

Wir definieren die Funktion, die wir an execute übergeben wollen, direkt dort, wo execute sein erstes Argument annimmt.

Auf diese Weise müssen wir der Funktion nicht einmal einen Namen geben, weshalb sie als anonyme Funktion bezeichnet wird.


Wie die Übergabe von Funktionen den HTTP-Server zum Laufen bringt

Mit diesem Wissen werfen wir noch einmal einen Blick auf unseren einfachen, aber nicht ganz so einfachen HTTP-Server:

Beispiel

var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}).listen(8888);

Jetzt sollte es viel klarer aussehen: Wir übergeben eine anonyme Funktion an die Funktion createServer.

Derselbe Zweck kann mit Code wie diesem erreicht werden:

Beispiel

var http = require("http");

function onRequest(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World");
  response.end();
}

http.createServer(onRequest).listen(8888);

Best Practices für Funktionen

Designprinzipien für Funktionen

  1. Einzelverantwortung: Eine Funktion erledigt nur eine Sache
  2. Sinnvolle Benennung: Verwende Verb + Substantiv (z. B.getUserInfo)
  3. Länge kontrollieren: Es wird empfohlen, 20 Codezeilen nicht zu überschreiten
  4. Seiteneffekte vermeiden: Reine Funktionen sind leichter zu testen und zu warten

Tipps zur Leistungsoptimierung

Beispiel

// Verwende eine Closure, um Ergebnisse zwischenzuspeichern
function memoize(fn) {
  const cache = new Map();
  return (...args) => {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
}

Praktische Übung

Übung 1: Erstellen einer Temperaturumrechnungsfunktion

Beispiel

/**
* Zwischen Celsius und Fahrenheit umrechnen
* @param {number} temp - Temperaturwert
* @param {string} unit - Ursprüngliche Einheit ('C' oder 'F')
* @returns {number} Umgerechnete Temperatur
 */

function convertTemperature(temp, unit) {
  // Dein Code...
}

Übung 2: Einen einfachen Event-Emitter implementieren

Beispiel

class EventEmitter {
  constructor() {
    this.events = {};
  }
 
  // Implementiere die on/emit/off-Methoden
}
Andere Erweiterungen