Kapitel 12. Strings
Inhaltsverzeichnis
Das Buch kaufen
(Werbung, bitte nicht blockieren.)

Kapitel 12. Strings

Strings sind unveränderliche Sequenzen von JavaScript-Zeichen. Jedes solche Zeichen ist eine 16-Bit-UTF-16-Code-Einheit. Das bedeutet, dass ein einzelnes Unicode-Zeichen entweder durch ein oder zwei JavaScript-Zeichen dargestellt wird. Sie müssen sich hauptsächlich mit dem Zwei-Zeichen-Fall beschäftigen, wenn Sie Zeichen zählen oder Strings aufteilen (siehe Kapitel 24).

String-Literale

Sowohl einfache als auch doppelte Anführungszeichen können verwendet werden, um String-Literale abzugrenzen:

'He said: "Hello"'
"He said: \"Hello\""

'Everyone\'s a winner'
"Everyone's a winner"

Somit sind Sie frei, jede Art von Anführungszeichen zu verwenden. Es gibt jedoch einige Überlegungen:

  • Der gebräuchlichste Stil in der Community ist die Verwendung von doppelten Anführungszeichen für HTML und einfachen Anführungszeichen für JavaScript.
  • Andererseits werden doppelte Anführungszeichen in einigen Sprachen (z. B. C und Java) ausschließlich für Strings verwendet. Daher kann es sinnvoll sein, sie in einer Codebasis mit mehreren Sprachen zu verwenden.
  • Für JSON (diskutiert in Kapitel 22) müssen Sie doppelte Anführungszeichen verwenden.

Ihr Code wird sauberer aussehen, wenn Sie konsistent zitieren. Aber manchmal bedeutet ein anderes Anführungszeichen, dass Sie nicht escapen müssen, was Ihre inkonsistentere Verwendung rechtfertigen kann (z. B. verwenden Sie normalerweise einfache Anführungszeichen, wechseln aber vorübergehend zu doppelten, um das letzte der vorherigen Beispiele zu schreiben).

Escaping in String-Literalen

Die meisten Zeichen in String-Literalen repräsentieren sich selbst. Der Backslash wird für Escaping verwendet und ermöglicht mehrere spezielle Funktionen:

Zeilenfortsetzungen

Sie können einen String über mehrere Zeilen verteilen, indem Sie das Ende der Zeile (das Zeilenabschlusszeichen, den Zeilenabschluss) mit einem Backslash escapen:

var str = 'written \
over \
multiple \
lines';
console.log(str === 'written over multiple lines'); // true

Eine Alternative ist die Verwendung des Plus-Operators zur Verkettung:

var str = 'written ' +
          'over ' +
          'multiple ' +
          'lines';
Zeichen-Escape-Sequenzen

Diese Sequenzen beginnen mit einem Backslash:

  • Steuerzeichen: \b ist ein Backspace, \f ist ein Formfeed, \n ist ein Zeilenvorschub (Newline), \r ist ein Wagenrücklauf, \t ist ein horizontaler Tabulator und \v ist ein vertikaler Tabulator.
  • Escapte Zeichen, die sich selbst repräsentieren: \' ist ein einfaches Anführungszeichen, \" ist ein doppeltes Anführungszeichen und \\ ist ein Backslash. Alle Zeichen außer b f n r t v x u und Dezimalziffern repräsentieren sich ebenfalls selbst. Hier sind zwei Beispiele

    > '\"'
    '"'
    > '\q'
    'q'
NUL-Zeichen (Unicode-Codepunkt 0)
Dieses Zeichen wird durch \0 dargestellt.
Hexadezimale Escape-Sequenzen

\xHH (HH sind zwei hexadezimale Ziffern) spezifiziert ein Zeichen über einen ASCII-Code. Zum Beispiel:

> '\x4D'
'M'
Unicode-Escape-Sequenzen

\uHHHH (HHHH sind vier hexadezimale Ziffern) spezifiziert eine UTF-16-Code-Einheit (siehe Kapitel 24). Hier sind zwei Beispiele

> '\u004D'
'M'
> '\u03C0'
'π'

Zeichenzugriff

Es gibt zwei Operationen, die das n-te Zeichen eines Strings zurückgeben.[16] Beachten Sie, dass JavaScript keinen speziellen Datentyp für Zeichen hat; diese Operationen geben Strings zurück

> 'abc'.charAt(1)
'b'
> 'abc'[1]
'b'

Einige ältere Browser unterstützen den array-ähnlichen Zugriff auf Zeichen über eckige Klammern nicht.

Konvertierung zu String

Werte werden wie folgt in einen String konvertiert:

WertErgebnis

undefined

'undefined'

null

'null'

Ein boolescher Wert

false'false'

true'true'

Eine Zahl

Die Zahl als String (z. B. 3.141'3.141')

Ein String

Identisch mit der Eingabe (keine Konvertierung erforderlich)

Ein Objekt

Rufen Sie ToPrimitive(value, String) auf (siehe Algorithmus: ToPrimitive()—Konvertierung eines Werts in ein Primitiv) und konvertieren Sie das resultierende Primitiv.

Manuelle Konvertierung zu String

Die drei gängigsten Methoden, um jeden Wert in einen String zu konvertieren, sind:

String(value)

(Als Funktion aufgerufen, nicht als Konstruktor)

''+value

value.toString()

(Funktioniert nicht für undefined und null!)

Ich bevorzuge String(), da es aussagekräftiger ist. Hier sind einige Beispiele

> String(false)
'false'
> String(7.35)
'7.35'
> String({ first: 'John', last: 'Doe' })
'[object Object]'
> String([ 'a', 'b', 'c' ])
'a,b,c'

Beachten Sie, dass für die Anzeige von Daten JSON.stringify() (JSON.stringify(value, replacer?, space?)) oft besser funktioniert als die kanonische Konvertierung in einen String:

> console.log(JSON.stringify({ first: 'John', last: 'Doe' }))
{"first":"John","last":"Doe"}
> console.log(JSON.stringify([ 'a', 'b', 'c' ]))
["a","b","c"]

Natürlich müssen Sie sich der Einschränkungen von JSON.stringify() bewusst sein – es zeigt nicht immer alles. Zum Beispiel verbirgt es Eigenschaften, deren Werte es nicht verarbeiten kann (Funktionen und mehr!). Auf der positiven Seite kann seine Ausgabe von eval() analysiert werden und es kann tief verschachtelte Daten als gut formatierte Bäume anzeigen.

Fallstrick: Konvertierung ist nicht invertierbar

Angesichts der Häufigkeit, mit der JavaScript automatisch konvertiert, ist es schade, dass die Konvertierung nicht immer invertierbar ist, insbesondere in Bezug auf boolesche Werte:

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

Bei undefined und null treten ähnliche Probleme auf.

Strings vergleichen

Es gibt zwei Möglichkeiten, Strings zu vergleichen. Erstens können Sie die Vergleichsoperatoren verwenden: <, >, ===, <=, >=. Sie haben die folgenden Nachteile:

  • Sie sind case-sensitiv

    > 'B' > 'A'  // ok
    true
    > 'B' > 'a'  // should be true
    false
  • Sie behandeln Umlaute und Akzente nicht gut

    > 'ä' < 'b'  // should be true
    false
    > 'é' < 'f'  // should be true
    false

Zweitens können Sie String.prototype.localeCompare(other) verwenden, was tendenziell besser abschneidet, aber nicht immer unterstützt wird (siehe Suchen und Vergleichen für Details). Das Folgende ist eine Interaktion in der Konsole von Firefox

> 'B'.localeCompare('A')
2
> 'B'.localeCompare('a')
2

> 'ä'.localeCompare('b')
-2
> 'é'.localeCompare('f')
-2

Ein Ergebnis kleiner als Null bedeutet, dass der Empfänger „kleiner“ als das Argument ist. Ein Ergebnis größer als Null bedeutet, dass der Empfänger „größer“ als das Argument ist.

Strings verketten

Es gibt zwei Hauptansätze, um Strings zu verketten.

Verkettung: Der Plus-Operator (+)

Der Operator + verkettet Strings, sobald einer seiner Operanden ein String ist. Wenn Sie String-Teile in einer Variablen sammeln möchten, ist der zusammengesetzte Zuweisungsoperator += nützlich:

> var str = '';
> str += 'Say hello ';
> str += 7;
> str += ' times fast!';
> str
'Say hello 7 times fast!'

Verkettung: Zusammenfügen eines Arrays von String-Fragmenten

Es mag den Anschein haben, dass der vorherige Ansatz bei jedem Hinzufügen eines Teils zu str einen neuen String erstellt. Ältere JavaScript-Engines machen es so, was bedeutet, dass Sie die Leistung der String-Verkettung verbessern können, indem Sie zuerst alle Teile in einem Array sammeln und sie als letzten Schritt zusammenfügen:

> var arr = [];

> arr.push('Say hello ');
> arr.push(7);
> arr.push(' times fast');

> arr.join('')
'Say hello 7 times fast'

Neuere Engines optimieren jedoch die String-Verkettung über + und verwenden intern eine ähnliche Methode. Daher ist der Plus-Operator auf diesen Engines schneller.

Die Funktion String

Die Funktion String kann auf zwei Arten aufgerufen werden:

String(value)

Als normale Funktion konvertiert sie value in einen primitiven String (siehe Konvertierung zu String)

> String(123)
'123'
> typeof String('abc')  // no change
'string'
new String(str)

Als Konstruktor erstellt sie eine neue Instanz von String (siehe Wrapper-Objekte für Primitive), ein Objekt, das str umschließt (Nicht-Strings werden zu Strings koerziert). Zum Beispiel

> typeof new String('abc')
'object'

Der erstere Aufruf ist der gebräuchlichste.

String-Konstruktor-Methode

String.fromCharCode(codeUnit1, codeUnit2, ...) erzeugt einen String, dessen Zeichen die UTF-16-Code-Einheiten sind, die durch die 16-Bit-Ganzzahlen codeUnit1, codeUnit2 und so weiter angegeben werden. Zum Beispiel:

> String.fromCharCode(97, 98, 99)
'abc'

Wenn Sie ein Array von Zahlen in einen String umwandeln möchten, können Sie dies über apply() tun (siehe func.apply(thisValue, argArray))

> String.fromCharCode.apply(null, [97, 98, 99])
'abc'

Das Inverse von String.fromCharCode() ist String.prototype.charCodeAt().

String-Instanzeigenschaft length

Die Eigenschaft length gibt die Anzahl der JavaScript-Zeichen im String an und ist unveränderlich:

> 'abc'.length
3

String-Prototyp-Methoden

Alle Methoden von primitiven Strings sind in String.prototype gespeichert (siehe auch Primitive leihen sich ihre Methoden von Wrappern). Im Folgenden beschreibe ich, wie sie für primitive Strings funktionieren, nicht für Instanzen von String.

Teilstrings extrahieren

Die folgenden Methoden extrahieren Teilstrings aus dem Empfänger

String.prototype.charAt(pos)

Gibt einen String mit dem Zeichen an Position pos zurück. Zum Beispiel:

> 'abc'.charAt(1)
'b'

Die folgenden beiden Ausdrücke ergeben dasselbe Ergebnis, aber einige ältere JavaScript-Engines unterstützen nur charAt() für den Zeichenzugriff

str.charAt(n)
str[n]
String.prototype.charCodeAt(pos)

Gibt den Code (eine 16-Bit-Ganzzahl) des JavaScript-Zeichens (einer UTF-16-Code-Einheit; siehe Kapitel 24) an Position pos zurück.

So erstellen Sie ein Array von Zeichencodes:

> 'abc'.split('').map(function (x) { return x.charCodeAt(0) })
[ 97, 98, 99 ]

Das Inverse von charCodeAt() ist String.fromCharCode().

String.prototype.slice(start, end?)

Gibt den Teilstring zurück, der bei Position start beginnt und bis zur Position end (exklusive) reicht. Beide Parameter können negativ sein, und dann wird die length des Strings zu ihnen addiert:

> 'abc'.slice(2)
'c'
> 'abc'.slice(1, 2)
'b'
> 'abc'.slice(-2)
'bc'
String.prototype.substring(start, end?)
Sollte zugunsten von slice() vermieden werden, das ähnlich ist, aber negative Positionen verarbeiten kann und über Browser hinweg konsistenter implementiert ist.
String.prototype.split(separator?, limit?)

Extrahiert die Teilstrings des Empfängers, die durch separator abgegrenzt sind, und gibt sie in einem Array zurück. Die Methode hat zwei Parameter:

  • separator: Entweder ein String oder ein regulärer Ausdruck. Wenn fehlend, wird der vollständige String zurückgegeben, in ein Array verpackt.
  • limit: Wenn angegeben, enthält das zurückgegebene Array höchstens limit Elemente.

Hier sind einige Beispiele

> 'a,  b,c, d'.split(',')  // string
[ 'a', '  b', 'c', ' d' ]
> 'a,  b,c, d'.split(/,/)  // simple regular expression
[ 'a', '  b', 'c', ' d' ]
> 'a,  b,c, d'.split(/, */)   // more complex regular expression
[ 'a', 'b', 'c', 'd' ]
> 'a,  b,c, d'.split(/, */, 2)  // setting a limit
[ 'a', 'b' ]
> 'test'.split()  // no separator provided
[ 'test' ]

Wenn es eine Gruppe gibt, werden die Übereinstimmungen ebenfalls als Array-Elemente zurückgegeben

> 'a,  b  ,  '.split(/(,)/)
[ 'a', ',', '  b  ', ',', '  ' ]
> 'a,  b  ,  '.split(/ *(,) */)
[ 'a', ',', 'b', ',', '' ]

Verwenden Sie '' (leerer String) als Trennzeichen, um ein Array mit den Zeichen eines Strings zu erstellen

> 'abc'.split('')
[ 'a', 'b', 'c' ]

Transformation

Während sich der vorherige Abschnitt mit der Extraktion von Teilstrings befasste, befasst sich dieser Abschnitt mit der Transformation eines gegebenen Strings in einen neuen. Diese Methoden werden typischerweise wie folgt verwendet:

var str = str.trim();

Mit anderen Worten, der ursprüngliche String wird verworfen, nachdem er (nicht-destruktiv) transformiert wurde

String.prototype.trim()

Entfernt alle Leerzeichen vom Anfang und Ende des Strings:

> '\r\nabc \t'.trim()
'abc'
String.prototype.concat(str1?, str2?, ...)

Gibt die Verkettung des Empfängers und von str1, str2 usw. zurück:

> 'hello'.concat(' ', 'world', '!')
'hello world!'
String.prototype.toLowerCase()

Erstellt einen neuen String, bei dem alle Zeichen des ursprünglichen Strings in Kleinbuchstaben umgewandelt wurden:

> 'MJÖLNIR'.toLowerCase()
'mjölnir'
String.prototype.toLocaleLowerCase()
Funktioniert genauso wie toLowerCase(), berücksichtigt aber die Regeln des aktuellen Gebietsschemas. Laut der ECMAScript-Spezifikation: „Es wird nur in wenigen Fällen (wie z. B. Türkisch) einen Unterschied geben, in denen die Regeln für diese Sprache mit den regulären Unicode-Groß-/Kleinschreibungsumwandlungen kollidieren.“
String.prototype.toUpperCase()

Erstellt einen neuen String, bei dem alle Zeichen des ursprünglichen Strings in Großbuchstaben umgewandelt wurden:

> 'mjölnir'.toUpperCase()
'MJÖLNIR'
String.prototype.toLocaleUpperCase()
Funktioniert genauso wie toUpperCase(), berücksichtigt aber die Regeln des aktuellen Gebietsschemas.

Suchen und Vergleichen

Die folgenden Methoden werden zum Suchen und Vergleichen von Strings verwendet:

String.prototype.indexOf(searchString, position?)

Sucht nach searchString beginnend bei position (Standard ist 0). Es gibt die Position zurück, an der searchString gefunden wurde, oder –1, wenn es nicht gefunden werden kann

> 'aXaX'.indexOf('X')
1
> 'aXaX'.indexOf('X', 2)
3

Beachten Sie, dass ein regulärer Ausdruck beim Finden von Text innerhalb eines Strings genauso gut funktioniert. Zum Beispiel sind die folgenden beiden Ausdrücke gleichwertig:

str.indexOf('abc') >= 0
/abc/.test(str)
String.prototype.lastIndexOf(searchString, position?)

Sucht rückwärts nach searchString, beginnend bei position (Standard ist das Ende). Es gibt die Position zurück, an der searchString gefunden wurde, oder –1, wenn es nicht gefunden werden kann:

> 'aXaX'.lastIndexOf('X')
3
> 'aXaX'.lastIndexOf('X', 2)
1
String.prototype.localeCompare(other)

Führt einen sprachabhängigen Vergleich des Strings mit other durch. Es gibt eine Zahl zurück:

  • < 0, wenn der String vor other kommt
  • = 0, wenn der String gleichwertig mit other ist
  • > 0, wenn der String nach other kommt

Zum Beispiel

> 'apple'.localeCompare('banana')
-2
> 'apple'.localeCompare('apple')
0

Warnung

Nicht alle JavaScript-Engines implementieren diese Methode korrekt. Einige basieren sie nur auf den Vergleichsoperatoren. Die ECMAScript Internationalization API (siehe Die ECMAScript Internationalization API) bietet jedoch eine Unicode-bewusste Implementierung. Das heißt, wenn diese API in einer Engine verfügbar ist, funktioniert localeCompare().

Wenn localeCompare() unterstützt wird, ist es eine bessere Wahl für den Vergleich von Strings als die Vergleichsoperatoren. Weitere Informationen finden Sie unter Strings vergleichen.

Testen, Abgleichen und Ersetzen mit regulären Ausdrücken

Die folgenden Methoden arbeiten mit regulären Ausdrücken

String.prototype.search(regexp) (ausführlicher erklärt in String.prototype.search: An welchem Index gibt es eine Übereinstimmung?)

Gibt den ersten Index zurück, an dem regexp im Empfänger übereinstimmt (oder –1, wenn nicht):

> '-yy-xxx-y-'.search(/x+/)
4
String.prototype.match(regexp) (ausführlicher erklärt in String.prototype.match: Erfassungsgruppen oder Rückgabe aller übereinstimmenden Teilstrings)

Gleicht den gegebenen regulären Ausdruck mit dem Empfänger ab. Es gibt ein Match-Objekt für die erste Übereinstimmung zurück, wenn das Flag /g von regexp nicht gesetzt ist:

> '-abb--aaab-'.match(/(a+)b/)
[ 'ab',
  'a',
  index: 1,
  input: '-abb--aaab-' ]

Wenn das Flag /g gesetzt ist, werden alle vollständigen Übereinstimmungen (Gruppe 0) in einem Array zurückgegeben

> '-abb--aaab-'.match(/(a+)b/g)
[ 'ab', 'aaab' ]
String.prototype.replace(search, replacement) (ausführlicher erklärt in String.prototype.replace: Suchen und Ersetzen)

Sucht nach search und ersetzt es durch replacement. search kann ein String oder ein regulärer Ausdruck sein, und replacement kann ein String oder eine Funktion sein. Sofern Sie keinen regulären Ausdruck als search verwenden, dessen Flag /g gesetzt ist, wird nur das erste Vorkommen ersetzt

> 'iixxxixx'.replace('i', 'o')
'oixxxixx'
> 'iixxxixx'.replace(/i/, 'o')
'oixxxixx'
> 'iixxxixx'.replace(/i/g, 'o')
'ooxxxoxx'

Ein Dollarzeichen ($) in einem Ersetzungsstring ermöglicht es Ihnen, auf die vollständige Übereinstimmung oder eine erfasste Gruppe zu verweisen:

> 'iixxxixx'.replace(/i+/g, '($&)') // complete match
'(ii)xxx(i)xx'
> 'iixxxixx'.replace(/(i+)/g, '($1)') // group 1
'(ii)xxx(i)xx'

Sie können eine Ersetzung auch über eine Funktion berechnen

> function repl(all) { return '('+all.toUpperCase()+')' }
> 'axbbyyxaa'.replace(/a+|b+/g, repl)
'(A)x(BB)yyx(AA)'



[16] Genau genommen besteht ein JavaScript-String aus einer Sequenz von UTF-16-Code-Einheiten. Das heißt, JavaScript-Zeichen sind Unicode-Code-Einheiten (siehe Kapitel 24).

Weiter: 13. Anweisungen