JavaScript für ungeduldige Programmierer (ES2022-Ausgabe)
Bitte unterstützen Sie dieses Buch: kaufen Sie es oder spenden Sie
(Werbung, bitte nicht blockieren.)

20 Strings



20.1 Spickzettel: Strings

Strings sind primitive Werte in JavaScript und unveränderlich. Das bedeutet, dass stringbezogene Operationen immer neue Strings erzeugen und niemals bestehende Strings ändern.

20.1.1 Arbeiten mit Strings

Literale für Strings

const str1 = 'Don\'t say "goodbye"'; // string literal
const str2 = "Don't say \"goodbye\""; // string literals
assert.equal(
  `As easy as ${123}!`, // template literal
  'As easy as 123!',
);

Backslashes werden verwendet, um

Innerhalb eines String.raw-getaggten Templates (Zeile A) werden Backslashes als normale Zeichen behandelt.

assert.equal(
  String.raw`\ \n\t`, // (A)
  '\\ \\n\\t',
);

Umwandlung von Werten in Strings

> String(undefined)
'undefined'
> String(null)
'null'
> String(123.45)
'123.45'
> String(true)
'true'

Kopieren von Teilen eines Strings

// There is no type for characters;
// reading characters produces strings:
const str3 = 'abc';
assert.equal(
  str3[2], 'c' // no negative indices allowed
);
assert.equal(
  str3.at(-1), 'c' // negative indices allowed
);

// Copying more than one character:
assert.equal(
  'abc'.slice(0, 2), 'ab'
);

Verketten von Strings

assert.equal(
  'I bought ' + 3 + ' apples',
  'I bought 3 apples',
);

let str = '';
str += 'I bought ';
str += 3;
str += ' apples';
assert.equal(
  str, 'I bought 3 apples',
);

20.1.2 JavaScript-Zeichen vs. Code Points vs. Grapheme Cluster

JavaScript-Zeichen sind 16 Bit groß. Sie sind es, was in Strings indiziert wird und was .length zählt.

Code Points sind die atomaren Teile von Unicode-Text. Die meisten von ihnen passen in ein JavaScript-Zeichen, einige belegen zwei (insbesondere Emojis).

assert.equal(
  'A'.length, 1
);
assert.equal(
  '🙂'.length, 2
);

Grapheme Cluster (vom Benutzer wahrgenommene Zeichen) repräsentieren geschriebene Symbole. Jeder besteht aus einem oder mehreren Code Points.

Aufgrund dieser Tatsachen sollten wir Text nicht in JavaScript-Zeichen aufteilen, sondern in Grapheme. Weitere Informationen zur Textverarbeitung finden Sie in §20.7 „Atome des Textes: Code Points, JavaScript-Zeichen, Grapheme Cluster“.

20.1.3 String-Methoden

Dieser Unterabschnitt gibt einen kurzen Überblick über die String-API. Am Ende dieses Kapitels finden Sie eine umfassendere Schnellreferenz.

Unterstrings finden

> 'abca'.includes('a')
true
> 'abca'.startsWith('ab')
true
> 'abca'.endsWith('ca')
true

> 'abca'.indexOf('a')
0
> 'abca'.lastIndexOf('a')
3

Aufteilen und Zusammenfügen

assert.deepEqual(
  'a, b,c'.split(/, ?/),
  ['a', 'b', 'c']
);
assert.equal(
  ['a', 'b', 'c'].join(', '),
  'a, b, c'
);

Auffüllen und Abschneiden

> '7'.padStart(3, '0')
'007'
> 'yes'.padEnd(6, '!')
'yes!!!'

> '\t abc\n '.trim()
'abc'
> '\t abc\n '.trimStart()
'abc\n '
> '\t abc\n '.trimEnd()
'\t abc'

Wiederholen und Groß-/Kleinschreibung ändern

> '*'.repeat(5)
'*****'
> '= b2b ='.toUpperCase()
'= B2B ='
> 'ΑΒΓ'.toLowerCase()
'αβγ'

20.2 Einfache String-Literale

Einfache String-Literale werden entweder von einfachen oder doppelten Anführungszeichen umschlossen.

const str1 = 'abc';
const str2 = "abc";
assert.equal(str1, str2);

Einfache Anführungszeichen werden häufiger verwendet, da sie die Erwähnung von HTML erleichtern, wo doppelte Anführungszeichen bevorzugt werden.

Das nächste Kapitel behandelt Template-Literale, die uns Folgendes bieten:

20.2.1 Escaping

Der Backslash ermöglicht es uns, Sonderzeichen zu erzeugen

Der Backslash ermöglicht es uns auch, den Begrenzer eines String-Literals innerhalb dieses Literals zu verwenden.

assert.equal(
  'She said: "Let\'s go!"',
  "She said: \"Let's go!\"");

20.3 Zugriff auf JavaScript-Zeichen

JavaScript hat keinen separaten Datentyp für Zeichen – Zeichen werden immer als Strings dargestellt.

const str = 'abc';

// Reading a JavaScript character at a given index
assert.equal(str[1], 'b');

// Counting the JavaScript characters in a string:
assert.equal(str.length, 3);

Die Zeichen, die wir auf dem Bildschirm sehen, werden Grapheme Cluster genannt. Die meisten von ihnen werden durch einzelne JavaScript-Zeichen dargestellt. Es gibt jedoch auch Grapheme Cluster (insbesondere Emojis), die durch mehrere JavaScript-Zeichen dargestellt werden.

> '🙂'.length
2

Wie das funktioniert, wird in §20.7 „Atome des Textes: Code Points, JavaScript-Zeichen, Grapheme Cluster“ erklärt.

20.4 String-Verkettung über +

Wenn mindestens ein Operand ein String ist, konvertiert der Plus-Operator (+) alle Nicht-Strings in Strings und verkettet das Ergebnis.

assert.equal(3 + ' times ' + 4, '3 times 4');

Der Zuweisungsoperator += ist nützlich, wenn wir einen String Stück für Stück zusammensetzen möchten.

let str = ''; // must be `let`!
str += 'Say it';
str += ' one more';
str += ' time';

assert.equal(str, 'Say it one more time');

  Verkettung über + ist effizient

Die Verwendung von + zum Zusammensetzen von Strings ist recht effizient, da die meisten JavaScript-Engines dies intern optimieren.

  Übung: Strings verketten

exercises/strings/concat_string_array_test.mjs

20.5 Umwandlung in String

Dies sind drei Möglichkeiten, einen Wert x in einen String umzuwandeln:

Empfehlung: Verwenden Sie das beschreibende und sichere String().

Beispiele

assert.equal(String(undefined), 'undefined');
assert.equal(String(null), 'null');

assert.equal(String(false), 'false');
assert.equal(String(true), 'true');

assert.equal(String(123.45), '123.45');

Fallstrick für Booleans: Wenn wir einen Boolean über String() in einen String konvertieren, können wir ihn im Allgemeinen nicht über Boolean() zurückkonvertieren.

> String(false)
'false'
> Boolean('false')
true

Der einzige String, für den Boolean() false zurückgibt, ist der leere String.

20.5.1 Stringifizierung von Objekten

Einfache Objekte haben eine Standard-String-Darstellung, die nicht sehr nützlich ist.

> String({a: 1})
'[object Object]'

Arrays haben eine bessere String-Darstellung, aber sie verbergen immer noch viele Informationen.

> String(['a', 'b'])
'a,b'
> String(['a', ['b']])
'a,b'

> String([1, 2])
'1,2'
> String(['1', '2'])
'1,2'

> String([true])
'true'
> String(['true'])
'true'
> String(true)
'true'

Die Stringifizierung von Funktionen gibt ihren Quellcode zurück.

> String(function f() {return 4})
'function f() {return 4}'

20.5.2 Anpassen der Stringifizierung von Objekten

Wir können die eingebaute Methode zur Stringifizierung von Objekten überschreiben, indem wir die Methode toString() implementieren.

const obj = {
  toString() {
    return 'hello';
  }
};

assert.equal(String(obj), 'hello');

20.5.3 Eine alternative Methode zur Stringifizierung von Werten

Das JSON-Datenformat ist eine Textdarstellung von JavaScript-Werten. Daher kann JSON.stringify() auch verwendet werden, um Werte in Strings umzuwandeln.

> JSON.stringify({a: 1})
'{"a":1}'
> JSON.stringify(['a', ['b']])
'["a",["b"]]'

Der Nachteil ist, dass JSON nur null, Booleans, Zahlen, Strings, Arrays und Objekte unterstützt (die es immer so behandelt, als wären sie durch Objekt-Literale erstellt worden).

Tipp: Der dritte Parameter ermöglicht es uns, die mehrzeilige Ausgabe zu aktivieren und anzugeben, wie viel eingerückt werden soll – zum Beispiel.

console.log(JSON.stringify({first: 'Jane', last: 'Doe'}, null, 2));

Diese Anweisung erzeugt die folgende Ausgabe:

{
  "first": "Jane",
  "last": "Doe"
}

20.6 Vergleich von Strings

Strings können mit den folgenden Operatoren verglichen werden:

< <= > >=

Es gibt einen wichtigen Vorbehalt zu beachten: Diese Operatoren vergleichen basierend auf den numerischen Werten von JavaScript-Zeichen. Das bedeutet, dass die Reihenfolge, die JavaScript für Strings verwendet, anders ist als die, die in Wörterbüchern und Telefonbüchern verwendet wird.

> 'A' < 'B' // ok
true
> 'a' < 'B' // not ok
false
> 'ä' < 'b' // not ok
false

Der richtige Vergleich von Text liegt außerhalb des Rahmens dieses Buches. Er wird über die ECMAScript Internationalization API (Intl) unterstützt.

20.7 Atome des Textes: Code Points, JavaScript-Zeichen, Grapheme Cluster

Kurze Wiederholung von §19 „Unicode – eine kurze Einführung“.

Der folgende Code zeigt, dass ein einzelner Code Point aus einem oder zwei JavaScript-Zeichen besteht. Wir zählen letztere über .length.

// 3 code points, 3 JavaScript characters:
assert.equal('abc'.length, 3);

// 1 code point, 2 JavaScript characters:
assert.equal('🙂'.length, 2);

Die folgende Tabelle fasst die gerade untersuchten Konzepte zusammen:

Entität Größe Kodiert über
JavaScript-Zeichen (UTF-16 Code Unit) 16 Bit
Unicode Code Point 21 Bit 1–2 Code Units
Unicode Grapheme Cluster 1+ Code Points

20.7.1 Arbeiten mit Code Points

Lassen Sie uns die Werkzeuge von JavaScript für die Arbeit mit Code Points untersuchen.

Ein Unicode Code Point Escape ermöglicht es uns, einen Code Point hexadezimal (1–5 Ziffern) anzugeben. Es erzeugt ein oder zwei JavaScript-Zeichen.

> '\u{1F642}'
'🙂'

  Unicode-Escape-Sequenzen

In der ECMAScript-Sprachspezifikation werden Unicode Code Point Escapes und Unicode Code Unit Escapes (die wir später antreffen werden) als Unicode Escape Sequences bezeichnet.

String.fromCodePoint() konvertiert einen einzelnen Code Point in 1–2 JavaScript-Zeichen.

> String.fromCodePoint(0x1F642)
'🙂'

.codePointAt() konvertiert 1–2 JavaScript-Zeichen in einen einzelnen Code Point.

> '🙂'.codePointAt(0).toString(16)
'1f642'

Wir können einen String iterieren, was Code Points (nicht JavaScript-Zeichen) besucht. Die Iteration wird später in diesem Buch beschrieben. Eine Möglichkeit zur Iteration ist die Verwendung einer for-of-Schleife.

const str = '🙂a';
assert.equal(str.length, 3);

for (const codePointChar of str) {
  console.log(codePointChar);
}

// Output:
// '🙂'
// 'a'

Array.from() basiert ebenfalls auf der Iteration und besucht Code Points.

> Array.from('🙂a')
[ '🙂', 'a' ]

Das macht es zu einem guten Werkzeug zum Zählen von Code Points.

> Array.from('🙂a').length
2
> '🙂a'.length
3

20.7.2 Arbeiten mit Code Units (Zeichencodes)

Indizes und Längen von Strings basieren auf JavaScript-Zeichen (wie sie durch UTF-16 Code Units dargestellt werden).

Um eine Code Unit hexadezimal anzugeben, können wir einen Unicode Code Unit Escape mit genau vier Hexadezimalziffern verwenden.

> '\uD83D\uDE42'
'🙂'

Und wir können String.fromCharCode() verwenden. Zeichencode ist der Name der Standardbibliothek für Code Unit.

> String.fromCharCode(0xD83D) + String.fromCharCode(0xDE42)
'🙂'

Um den Zeichencode eines Zeichens zu erhalten, verwenden Sie .charCodeAt().

> '🙂'.charCodeAt(0).toString(16)
'd83d'

20.7.3 ASCII-Escapes

Wenn der Code Point eines Zeichens unter 256 liegt, können wir ihn über einen ASCII-Escape mit genau zwei Hexadezimalziffern referenzieren.

> 'He\x6C\x6Co'
'Hello'

(Der offizielle Name für ASCII-Escapes ist Hexadecimal escape sequences – es war der erste Escape, der Hexadezimalzahlen verwendete.)

20.7.4 Vorsicht: Grapheme Cluster

Beim Arbeiten mit Text, der in jeder menschlichen Sprache geschrieben sein kann, ist es am besten, an den Grenzen von Grapheme Clustern zu trennen, nicht an den Grenzen von Code Points.

TC39 arbeitet an Intl.Segmenter, einem Vorschlag für die ECMAScript Internationalization API zur Unterstützung der Unicode-Segmentierung (entlang von Grapheme Cluster-Grenzen, Wortgrenzen, Satzgrenzen usw.).

Bis dieser Vorschlag zum Standard wird, können wir eine der verschiedenen verfügbaren Bibliotheken verwenden (suchen Sie im Web nach „JavaScript grapheme“).

20.8 Schnellreferenz: Strings

20.8.1 Umwandlung in String

Tabelle 14 beschreibt, wie verschiedene Werte in Strings umgewandelt werden.

Tabelle 14: Umwandlung von Werten in Strings.
x String(x)
undefined 'undefined'
null 'null'
boolean false 'false', true 'true'
number Beispiel: 123 '123'
bigint Beispiel: 123n '123'
string x (Eingabe, unverändert)
symbol Beispiel: Symbol('abc') 'Symbol(abc)'
object Konfigurierbar über z.B. toString()

20.8.2 Numerische Werte von Textatomen

20.8.3 String.prototype: Suchen und Abgleichen

(String.prototype ist dort gespeichert, wo die Methoden von Strings sind.)

20.8.4 String.prototype: Extrahieren

20.8.5 String.prototype: Kombinieren

20.8.6 String.prototype: Transformieren

20.8.7 Quellen

  Übung: String-Methoden verwenden

exercises/strings/remove_extension_test.mjs

  Quiz

Siehe Quiz-App.