`String`-Objekt
In diesem Artikel wird das String-Objekt erklärt.
Die Erklärung umfasst alles von den Grundlagen bis zu fortgeschrittenen Techniken, einschließlich Fallstricke im Zusammenhang mit Unicode und regulären Ausdrücken, Schritt für Schritt und leicht verständlich.
YouTube Video
String-Objekt
Strings gehören in JavaScript zu den am häufigsten verwendeten Typen in der täglichen Entwicklung.
Unterschied zwischen primitiven Strings und String-Objekten
Primitive Strings (wie "hello") verhalten sich anders als Wrapper-Objekte wie new String("hello"). In der Regel sollten Sie primitive Strings verwenden; die Objektform ist kaum erforderlich.
1// Primitive string
2const a = "hello";
3
4// String wrapper object
5const b = new String("hello");
6
7console.log(typeof a); // "string"
8console.log(typeof b); // "object"
9console.log(a === b); // false — wrapper objects are not strictly equal
- Dieser Code zeigt den Typunterschied zwischen einem primitiven String und einem Wrapper sowie ihr Verhalten bei striktem Vergleich. Vermeiden Sie in den meisten Fällen die Verwendung von
new String()und verwenden Sie stattdessen primitive Strings.
Möglichkeiten zur Erstellung von Strings (Literale und Template-Literale)
Template-Literale eignen sich gut zum Einbetten von Variablen und für mehrzeilige Strings. Sie können Variablen intuitiv einfügen und Ausdrücke auswerten.
1const name = "Alice";
2const age = 30;
3
4// Template literal
5const greeting = `Name: ${name}, Age: ${age + 1}`;
6
7console.log(greeting); // "Name: Alice, Age: 31"
- Template-Literale sind sehr gut lesbar und ideal für den Aufbau komplexer, auch mehrzeiliger Strings.
Häufige Methoden (Suche und Extraktion von Teilstrings)
Das String-Objekt bietet viele grundlegende Methoden.
1const text = "Hello, world! Hello again.";
2
3// search
4console.log(text.indexOf("Hello")); // 0
5console.log(text.indexOf("Hello", 1)); // 13
6console.log(text.includes("world")); // true
7console.log(text.startsWith("Hello")); // true
8console.log(text.endsWith("again.")); // true
9
10// slice / substring
11console.log(text.slice(7, 12)); // "world"
12console.log(text.substring(7, 12)); // "world"
sliceundsubstringsind ähnlich, behandeln aber negative Indizes unterschiedlich.sliceinterpretiert negative Werte als Positionen vom Ende her. Seien Sie sich darüber im Klaren, welche Methode Sie verwenden.
Aufteilen und Zusammenfügen (split / join)
Es ist üblich, einen String zum Verarbeiten in ein Array aufzuteilen und anschließend wieder zusammenzufügen.
1const csv = "red,green,blue";
2const arr = csv.split(","); // ["red","green","blue"]
3
4console.log(arr);
5console.log(arr.join(" | ")); // "red | green | blue"
- Ein gängiges Muster ist, mit
spliteinen String aufzuteilen, das Array mitmapoderfilterzu verarbeiten und anschließend mitjoinwieder zusammenzufügen.
Ersetzen und reguläre Ausdrücke
replace ersetzt nur das erste Vorkommen. Um alle Vorkommen zu ersetzen, verwenden Sie das g-Flag in einem regulären Ausdruck. Durch Übergeben einer Funktion als Ersatz können Sie auch dynamische Ersetzungen durchführen.
1const s = "foo 1 foo 2";
2
3// replace first only
4console.log(s.replace("foo", "bar")); // "bar 1 foo 2"
5
6// replace all using regex
7console.log(s.replace(/foo/g, "bar")); // "bar 1 bar 2"
8
9// replace with function
10const r = s.replace(/\d+/g, (match) => String(Number(match) * 10));
11console.log(r); // "foo 10 foo 20"
- Mit der dynamischen Ersetzung per Funktion können Sie prägnanten Code schreiben, der Treffer analysiert und transformiert.
Groß-/Kleinschreibung und Normalisierung
Für mehrsprachige Unterstützung und Vergleiche ist neben toLowerCase und toUpperCase auch die Unicode-Normalisierung (normalize) wichtig. Dies ist besonders beim Vergleich von Zeichen mit Akzent erforderlich.
1// Case conversion example:
2// "\u00DF" represents the German letter "ß".
3// In some locales, converting "ß" to uppercase becomes "SS".
4// JavaScript follows this behavior.
5console.log("\u00DF");
6console.log("\u00DF".toUpperCase()); // "SS"
7
8// Unicode normalization example:
9// "e\u0301" is "e" + a combining acute accent.
10// "\u00e9" is the precomposed character "é".
11// These two look the same but are different code point sequences.
12const a = "e\u0301";
13const b = "\u00e9";
14
15console.log(a === b); // false: different underlying code points
16console.log(a.normalize() === b.normalize()); // true: normalized to the same form
- Unterschiedliche Unicode-Darstellungen, wie Ligaturen und kombinierende Zeichen, sind nicht direkt gleich – verwenden Sie daher vor dem Vergleich
normalize().
Unicode und Codepoints (Umgang mit Surrogatpaaren)
JavaScript-Strings sind Sequenzen von UTF-16-Code-Einheiten. Manche Zeichen, wie Emojis, belegen deshalb zwei Code-Einheiten für ein einzelnes Zeichen. Um tatsächliche Zeicheneinheiten zu verarbeiten, verwenden Sie Array.from, den Spread-Operator oder for...of.
1// Emoji composed with multiple code points:
2// "\u{1F469}" = woman, "\u{200D}" = Zero Width Joiner (ZWJ),
3// "\u{1F4BB}" = laptop. Combined, they form a single emoji: 👩💻
4const s = "\u{1F469}\u{200D}\u{1F4BB}";
5console.log(s);
6
7// Length in UTF-16 code units (not actual Unicode characters):
8// Because this emoji uses surrogate pairs + ZWJ, the length may be > 1.
9console.log("Length:", s.length);
10
11// Iterate by Unicode code points (ES6 for...of iterates code points):
12// Each iteration gives a full Unicode character, not UTF-16 units.
13for (const ch of s) {
14 console.log(ch);
15}
16
17// Convert to an array of Unicode characters:
18console.log(Array.from(s));lengthgibt die Anzahl der Code-Einheiten zurück, sodass Sie mit Emojis oder Ligaturen möglicherweise nicht den erwarteten Wert erhalten.for...ofundArray.fromerfassen fast die dargestellten Zeichen (Graphemcluster), aber für vollständige Graphem-Unterstützung sollten Sie eine spezialisierte Bibliothek verwenden.
Sicheres Ersetzen mit regulären Ausdrücken (bei Benutzereingaben)
Wenn Sie die Benutzereingabe nicht escapen, bevor Sie sie in einen regulären Ausdruck einbetten, kann dies zu unerwartetem Verhalten und Sicherheitslücken führen. Maskieren Sie Benutzereingaben immer, bevor Sie sie in einem Muster verwenden.
1function escapeRegex(s) {
2 return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3}
4
5const userInput = "a+b";
6const pattern = new RegExp(escapeRegex(userInput), "g");
7console.log("a+b a+b".replace(pattern, "X")); // "X X"
- Verwenden Sie Benutzereingaben niemals direkt in regulären Ausdrücken; maskieren Sie sie immer vor der Konstruktion des RegEx.
Performance-Tipps: Verkettung und Templates
Beim Verkettung vieler kleiner Strings hintereinander kann es effizienter sein, sie in ein Array zu legen und mit join zusammenzuführen. Andererseits sind Template-Strings sehr gut lesbar und in den meisten Fällen schnell genug.
1// concatenation in loop (less ideal)
2let s = "";
3for (let i = 0; i < 1000; i++) {
4 s += i + ",";
5}
6
7// using array + join (often faster for many pieces)
8const parts = [];
9for (let i = 0; i < 1000; i++) {
10 parts.push(i + ",");
11}
12const s2 = parts.join("");- Moderne JavaScript-Engines sind stark optimiert, daher ist die Performance bei wenigen Verkettungen kein Problem. Wenn Sie jedoch zehntausende Male verketten müssen, ist
joinmöglicherweise effizienter.
Nützliche praktische Techniken: Padding, Trim und Repeat
trim, padStart, padEnd und repeat sind praktische Methoden, die besonders bei der täglichen Zeichenkettenverarbeitung nützlich sind. Sie werden häufig in praktischen Situationen wie dem Formatieren von Eingabewerten oder dem Standardisieren von Ausgabeformaten verwendet.
1console.log(" hello ".trim()); // "hello"
2console.log("5".padStart(3, "0")); // "005"
3console.log("x".repeat(5)); // "xxxxx"
- Diese Methoden können zur Normalisierung von Formulareingaben oder zur Erzeugung von Ausgaben mit fester Breite verwendet werden.
String-Vergleich (lokale Sortierung)
localeCompare ist effektiv, um Strings entsprechend der Wörterbuchreihenfolge verschiedener Sprachen zu vergleichen. Sie können Sprache und Empfindlichkeitsoptionen (wie Groß-/Kleinschreibung) angeben.
1console.log(
2 "\u00E4".localeCompare("z", "de")
3); // may be -1 or other depending on locale
4
5console.log(
6 "a".localeCompare("A", undefined, { sensitivity: "base" })
7); // 0
- Für internationalisierte Vergleiche verwenden Sie
localeCompareund geben die passende Sprache sowie Optionen an.
Praktisches Beispiel: Umwandlung einer CSV-Zeile in ein Objekt (praktischer Workflow)
Ein häufiger Anwendungsfall ist das Parsen einer einzelnen CSV-Zeile zu einem Objekt durch Kombination von split, trim und map. Für Felder mit Anführungszeichen oder komplexe CSV-Dateien verwenden Sie einen spezialisierten CSV-Parser.
1// simple CSV parse (no quotes handling)
2function parseCsvLine(line, headers) {
3 const values = line.split(",").map(v => v.trim());
4 const obj = {};
5 headers.forEach((h, i) => obj[h] = values[i] ?? null);
6 return obj;
7}
8
9const headers = ["name", "age", "city"];
10const line = " Alice , 30 , New York ";
11console.log(parseCsvLine(line, headers));
12// { name: "Alice", age: "30", city: "New York" }
- Diese Methode funktioniert bei einfachen CSV-Dateien, kann jedoch keine Fälle mit Kommas in Anführungszeichen verarbeiten.
Häufige Fallstricke
Beim Arbeiten mit Strings in JavaScript gibt es einige leicht zu übersehende Spezifikationen und Verhaltensweisen. Um unerwartete Fehler zu vermeiden, sollten Sie die folgenden Punkte beachten.
- Die Verwendung von
new String()kann bei Typüberprüfung oder Vergleichen zu falschen Ergebnissen führen. In den meisten Fällen sind primitive String-Typen ausreichend. - Im Unicode kann ein einzelnes sichtbares Zeichen aus mehreren Code-Einheiten bestehen. Deshalb stimmt der von
lengthzurückgegebene Wert möglicherweise nicht mit der tatsächlichen Zeichenanzahl überein. - Wenn Sie Benutzereingaben in einen regulären Ausdruck einfügen, maskieren Sie diese immer vorher.
String.prototype.replace()ersetzt standardmäßig nur das erste Vorkommen. Wenn Sie alle Vorkommen ersetzen möchten, verwenden Sie das Flag/gin Ihrem regulären Ausdruck.- Strings sind unveränderlich, daher liefern Operationen stets einen neuen String zurück. Es ist wichtig, den zurückgegebenen Wert immer zuzuweisen.
Zusammenfassung
Auch wenn JavaScript-Strings einfach erscheinen, ist es wichtig, ihre Eigenschaften bezüglich Unicode und Unveränderlichkeit zu verstehen. Wenn Sie die Grundlagen beherrschen, steigern Sie die Zuverlässigkeit und Lesbarkeit Ihrer String-Verarbeitung erheblich.
Sie können den obigen Artikel mit Visual Studio Code auf unserem YouTube-Kanal verfolgen. Bitte schauen Sie sich auch den YouTube-Kanal an.