JavaScript-Datentypen und Datenstrukturen
Programmiersprachen verfügen alle über eingebaute Datenstrukturen, diese unterscheiden sich jedoch oft von Sprache zu Sprache. Dieser Artikel versucht, die in JavaScript verfügbaren eingebauten Datenstrukturen und deren Eigenschaften aufzulisten. Diese können verwendet werden, um andere Datenstrukturen aufzubauen.
Der Sprachenüberblick bietet eine ähnliche Zusammenfassung der üblichen Datentypen, jedoch mit mehr Vergleichen zu anderen Sprachen.
Dynamische und schwache Typisierung
JavaScript ist eine dynamische Sprache mit dynamischen Typen. Variablen in JavaScript sind nicht direkt mit einem bestimmten Wertetyp verbunden, und jede Variable kann (und darf) mit Werten aller Typen zugewiesen (und neu zugewiesen) werden:
let foo = 42; // foo is now a number
foo = "bar"; // foo is now a string
foo = true; // foo is now a boolean
JavaScript ist auch eine schwach typisierte Sprache, was bedeutet, dass sie implizite Typkonvertierungen zulässt, wenn eine Operation unpassende Typen beinhaltet, anstatt Typfehler zu erzeugen.
const foo = 42; // foo is a number
const result = foo + "1"; // JavaScript coerces foo to a string, so it can be concatenated with the other operand
console.log(result); // 421
Implizite Überführungen sind sehr praktisch, können jedoch subtile Fehler verursachen, wenn Überführungen dort passieren, wo sie nicht erwartet werden, oder wo erwartet wird, dass sie in die andere Richtung passieren (zum Beispiel von String zu Nummer anstatt von Nummer zu String). Für Symbole und BigInts hat JavaScript absichtlich bestimmte implizite Typkonvertierungen nicht zugelassen.
Primitive Werte
Alle Typen außer Object definieren unveränderliche Werte, die direkt auf der niedrigsten Ebene der Sprache dargestellt werden. Wir beziehen uns auf Werte dieser Typen als primitive Werte.
Alle primitiven Typen, außer null
, können durch den typeof
-Operator getestet werden. typeof null
gibt "object"
zurück, daher muss === null
verwendet werden, um auf null
zu testen.
Alle primitiven Typen, außer null
und undefined
, haben entsprechende Objekt-Wrapper-Typen, die nützliche Methoden zum Arbeiten mit den primitiven Werten bereitstellen. Zum Beispiel bietet das Number
-Objekt Methoden wie toExponential()
. Wenn auf eine Eigenschaft eines primitiven Wertes zugegriffen wird, umhüllt JavaScript den Wert automatisch mit dem entsprechenden Wrapper-Objekt und greift stattdessen auf die Eigenschaft des Objekts zu. Das Zugreifen auf eine Eigenschaft von null
oder undefined
wirft jedoch eine TypeError
-Ausnahme, was die Einführung des optionalen Verkettungsoperators erforderlich machte.
Typ | typeof Rückgabewert |
Objekt-Wrapper |
---|---|---|
Null | "object" |
N/A |
Undefined | "undefined" |
N/A |
Boolean | "boolean" |
Boolean |
Number | "number" |
Number |
BigInt | "bigint" |
BigInt |
String | "string" |
String |
Symbol | "symbol" |
Symbol |
Die Referenzseiten der Objekt-Wrapper-Klassen enthalten mehr Informationen über die verfügbaren Methoden und Eigenschaften für jeden Typ sowie detaillierte Beschreibungen zu den Semantiken der primitiven Typen selbst.
Null-Typ
Der Null-Typ wird genau durch einen Wert bewohnt: null
.
Undefined-Typ
Der Undefined-Typ wird genau durch einen Wert bewohnt: undefined
.
Konzeptionell zeigt undefined
die Abwesenheit eines Wertes an, während null
das Fehlen eines Objekts kennzeichnet (was auch eine Ausrede für typeof null === "object"
sein könnte). Die Sprache setzt normalerweise undefined
als Standardwert, wenn etwas keinen Wert hat:
- Eine
return
-Anweisung ohne Wert (return;
) gibt implizitundefined
zurück. - Der Zugriff auf eine nicht existierende Objekt-Eigenschaft (
obj.iDontExist
) gibtundefined
zurück. - Eine Variablendeklaration ohne Initialisierung (
let x;
) initialisiert die Variable implizit mitundefined
. - Viele Methoden, wie
Array.prototype.find()
undMap.prototype.get()
, gebenundefined
zurück, wenn kein Element gefunden wird.
null
wird in der Kernsprache viel seltener verwendet. Der wichtigste Ort ist das Ende der Prototypenkette — folglich akzeptieren oder geben Methoden, die mit Prototypen interagieren, wie Object.getPrototypeOf()
, Object.create()
usw., null
statt undefined
zurück.
null
ist ein Schlüsselwort, aber undefined
ist ein normales Identifikator, das zufällig eine globale Eigenschaft ist. In der Praxis ist der Unterschied gering, da undefined
nicht neu definiert oder überschattet werden sollte.
Boolean-Typ
Der Boolean
-Typ stellt eine logische Entität dar und wird von zwei Werten bewohnt: true
und false
.
Boolesche Werte werden üblicherweise für bedingte Operationen verwendet, einschließlich ternärer Operatoren, if...else
, while
usw.
Number-Typ
Der Number
-Typ ist ein doppelter 64-Bit-Gleitkommawert im IEEE 754-Format. Er kann positive Gleitkommazahlen zwischen 2-1074 (Number.MIN_VALUE
) und 21023 × (2 - 2-52) (Number.MAX_VALUE
) sowie negative Gleitkommazahlen derselben Größenordnung speichern, jedoch kann er ganze Zahlen nur im Bereich von -(253 − 1) (Number.MIN_SAFE_INTEGER
) bis 253 − 1 (Number.MAX_SAFE_INTEGER
) sicher speichern. Außerhalb dieses Bereichs kann JavaScript ganze Zahlen nicht mehr sicher darstellen; sie werden stattdessen im doppelten Gleitkomma-Format angenähert. Sie können überprüfen, ob eine Zahl innerhalb des Bereichs der sicheren Ganzzahlen liegt, indem Sie Number.isSafeInteger()
verwenden.
Werte außerhalb des darstellbaren Bereichs werden automatisch umgewandelt:
- Positive Werte größer als
Number.MAX_VALUE
werden in+Infinity
umgewandelt. - Positive Werte kleiner als
Number.MIN_VALUE
werden in+0
umgewandelt. - Negative Werte kleiner als -
Number.MAX_VALUE
werden in-Infinity
umgewandelt. - Negative Werte größer als -
Number.MIN_VALUE
werden in-0
umgewandelt.
+Infinity
und -Infinity
verhalten sich ähnlich wie mathematische Unendlichkeit, jedoch mit einigen kleinen Unterschieden; siehe Number.POSITIVE_INFINITY
und Number.NEGATIVE_INFINITY
für Details.
Der Number-Typ hat nur einen Wert mit mehreren Darstellungen: 0
wird sowohl als -0
als auch als +0
dargestellt (wobei 0
ein Alias für +0
ist). In der Praxis gibt es fast keinen Unterschied zwischen den verschiedenen Darstellungen; zum Beispiel ist +0 === -0
true
. Sie können dies jedoch bemerken, wenn Sie durch null teilen:
console.log(42 / +0); // Infinity
console.log(42 / -0); // -Infinity
NaN
("Nicht eine Zahl") ist eine spezielle Art eines Zahlenwertes, der typischerweise auftritt, wenn das Ergebnis einer arithmetischen Operation nicht als Zahl ausgedrückt werden kann. Es ist auch der einzige Wert in JavaScript, der sich nicht selbst gleich ist.
Obwohl eine Zahl konzeptionell ein "mathematischer Wert" ist und immer implizit im Gleitkomma-Format codiert ist, bietet JavaScript bitweise Operatoren. Bei der Anwendung bitweiser Operatoren wird die Zahl zuerst in eine 32-Bit-Ganzzahl umgewandelt.
Hinweis: Obwohl bitweise Operatoren verwendet werden können, um mehrere Boolesche Werte in einer einzigen Zahl durch Bitmaskierung darzustellen, wird dies normalerweise als schlechte Praxis angesehen. JavaScript bietet andere Möglichkeiten, um eine Menge von Booleschen Werten darzustellen (wie ein Array von Booleschen, oder ein Objekt mit Booleschen Werten, die benannten Eigenschaften zugewiesen sind). Bitmaskierung neigt auch dazu, den Code weniger lesbar, verständlich und wartbar zu machen.
Es kann notwendig sein, solche Techniken in sehr beschränkten Umgebungen zu verwenden, wie beim Umgang mit den Einschränkungen des lokalen Speichers oder in extremen Fällen (wie wenn jedes Bit über das Netzwerk zählt). Diese Technik sollte nur in Betracht gezogen werden, wenn es das letzte Mittel ist, das zur Optimierung der Größe ergriffen werden kann.
BigInt-Typ
Der BigInt
-Typ ist ein numerischer primitiver Typ in JavaScript, der ganze Zahlen mit beliebiger Größe darstellen kann. Mit BigInts können Sie große Zahlen sicher speichern und mit ihnen operieren, selbst über die Grenze sicherer Ganzzahlen (Number.MAX_SAFE_INTEGER
) für Zahlen hinaus.
Ein BigInt wird erstellt, indem n
an das Ende einer ganzen Zahl angehängt oder die BigInt()
-Funktion aufgerufen wird.
Dieses Beispiel zeigt, wo das Erhöhen von Number.MAX_SAFE_INTEGER
das erwartete Ergebnis liefert:
// BigInt
const x = BigInt(Number.MAX_SAFE_INTEGER); // 9007199254740991n
x + 1n === x + 2n; // false because 9007199254740992n and 9007199254740993n are unequal
// Number
Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2; // true because both are 9007199254740992
Sie können die meisten Operatoren verwenden, um mit BigInts zu arbeiten, einschließlich +
, *
, -
, **
, und %
— der einzige verbotene Operator ist >>>
. Ein BigInt ist nicht streng gleich zu einer Zahl mit demselben mathematischen Wert, aber es ist lose so.
BigInt-Werte sind weder immer präziser noch immer unpräziser als Zahlen, da BigInts keine Bruchzahlen darstellen können, aber große Ganzzahlen genauer darstellen können. Kein Typ übernimmt den anderen, und sie sind nicht gegenseitig austauschbar. Ein TypeError
wird geworfen, wenn BigInt-Werte in arithmetischen Ausdrücken mit regulären Zahlen gemischt oder wenn sie implizit konvertiert werden.
String-Typ
Der String
-Typ stellt Textdaten dar und wird als eine Sequenz von 16-Bit-unsigned-Integer-Werten codiert, die UTF-16-Codeeinheiten darstellen. Jedes Element im String nimmt eine Position im String ein. Das erste Element befindet sich an Index 0
, das nächste an Index 1
usw. Die Länge eines Strings ist die Anzahl der UTF-16-Codeeinheiten darin, was möglicherweise nicht der tatsächlichen Anzahl an Unicode-Zeichen entspricht; siehe die String
-Referenzseite für weitere Details.
JavaScript-Strings sind unveränderlich. Das bedeutet, dass es nach der Erstellung eines Strings nicht möglich ist, ihn zu ändern. String-Methoden erstellen neue Strings basierend auf dem Inhalt des aktuellen Strings — zum Beispiel:
- Ein Substring des Originals durch
substring()
. - Eine Verkettung von zwei Strings mittels des Verkettungsoperators (
+
) oderconcat()
.
Vorsicht vor "stringly-typing"-Ihres Codes!
Es kann verlockend sein, Strings zu verwenden, um komplexe Daten darzustellen. Dies bringt kurzfristige Vorteile:
- Es ist einfach, komplexe Strings durch Verkettung zu erstellen.
- Strings sind leicht zu debuggen (was Sie sehen, ist immer das, was im String enthalten ist).
- Strings sind der gemeinsame Nenner vieler APIs (Eingabefelder, lokale Speicher-werte,
fetch()
-Antworten beim Verwenden vonResponse.text()
usw.), und es kann verlockend sein, nur mit Strings zu arbeiten.
Mit Konventionen ist es möglich, beliebige Datenstrukturen in einem String darzustellen. Dies macht es jedoch nicht zu einer guten Idee. Beispielsweise könnte man mit einem Separator eine Liste emulieren (während ein JavaScript-Array besser geeignet wäre). Leider wird die Liste aufgebrochen, sobald der Separator in einem der "Listen"-Elemente verwendet wird. Ein Escape-Zeichen kann gewählt werden usw. All das erfordert Konventionen und schafft eine unnötige Wartungslast.
Verwenden Sie Strings für Textdaten. Wenn komplexe Daten dargestellt werden, parsen Sie Strings und verwenden Sie die entsprechende Abstraktion.
Symbol-Typ
Ein Symbol
ist ein einzigartiger und unveränderlicher primitiver Wert und kann als Schlüssel einer Objekteigenschaft verwendet werden (siehe unten). In einigen Programmiersprachen werden Symbole als "Atoms" bezeichnet. Der Zweck von Symbolen ist es, eindeutige Eigenschaftsschlüssel zu erstellen, die garantiert nicht mit Schlüsseln aus anderem Code kollidieren.
Objekte
In der Informatik ist ein Objekt ein Wert im Speicher, der möglicherweise durch einen Identifikator referenziert wird. In JavaScript sind Objekte die einzigen veränderbaren Werte. Funktionen sind tatsächlich auch Objekte mit der zusätzlichen Fähigkeit, aufrufbar zu sein.
Eigenschaften
In JavaScript können Objekte als eine Sammlung von Eigenschaften betrachtet werden. Mit der Objektliteral-Syntax wird eine begrenzte Menge von Eigenschaften initialisiert; danach können Eigenschaften hinzugefügt und entfernt werden. Objekteigenschaften sind gleichbedeutend mit Schlüssel-Wert-Paaren. Eigenschaftsschlüssel sind entweder Strings oder Symbole. Wenn andere Typen (wie Zahlen) zur Indizierung von Objekten verwendet werden, werden die Werte implizit in Strings umgewandelt. Eigenschaftswerte können Werte jeglichen Typs sein, einschließlich anderer Objekte, was den Aufbau komplexer Datenstrukturen ermöglicht.
Es gibt zwei Arten von Objekteigenschaften: Die _Daten-_Eigenschaft und die _Zugriffs-_Eigenschaft. Jede Eigenschaft hat entsprechende Attribute. Jedes Attribut wird intern von der JavaScript-Engine zugegriffen, aber Sie können sie über Object.defineProperty()
festlegen oder über Object.getOwnPropertyDescriptor()
lesen. Sie können mehr über die verschiedenen Nuancen auf der Object.defineProperty()
-Seite lesen.
Daten-Eigenschaft
Daten-Eigenschaften verknüpfen einen Schlüssel mit einem Wert. Sie kann durch die folgenden Attribute beschrieben werden:
value
-
Der Wert, der durch einen Zugriff auf die Eigenschaft abgerufen wird. Kann jeder JavaScript-Wert sein.
writable
-
Ein boolescher Wert, der anzeigt, ob die Eigenschaft durch Zuweisung geändert werden kann.
enumerable
-
Ein boolescher Wert, der anzeigt, ob die Eigenschaft durch eine
for...in
-Schleife aufgezählt werden kann. Siehe auch Aufzählbarkeit und Eigentum von Eigenschaften für Informationen darüber, wie Aufzählbarkeit mit anderen Funktionen und Syntaxen interagiert. configurable
-
Ein boolescher Wert, der anzeigt, ob die Eigenschaft gelöscht oder in eine Zugriffs-Eigenschaft geändert werden kann und ob ihre Attribute geändert werden können.
Zugriffs-Eigenschaft
Verknüpft einen Schlüssel mit einer von zwei Zugriffs-Funktionen (get
und set
), um einen Wert abzurufen oder zu speichern.
Hinweis: Es ist wichtig zu erkennen, dass es sich um eine Zugriffs-Eigenschaft handelt — nicht um eine Zugriffs-Methode. Wir können einem JavaScript-Objekt klassenähnliche Zugriffsverfahren geben, indem wir eine Funktion als Wert verwenden — aber das macht das Objekt nicht zu einer Klasse.
Eine Zugriffs-Eigenschaft hat die folgenden Attribute:
get
-
Eine Funktion, die mit einer leeren Argumentliste aufgerufen wird, um den Eigenschaftswert abzurufen, wann immer ein Zugriff auf den Wert erfolgt. Siehe auch Get-Methoden. Kann
undefined
sein. set
-
Eine Funktion, die mit einem Argument, das den zugewiesenen Wert enthält, aufgerufen wird. Wird ausgeführt, wann immer eine bestimmte Eigenschaft versucht wird, geändert zu werden. Siehe auch Set-Methoden. Kann
undefined
sein. enumerable
-
Ein boolescher Wert, der anzeigt, ob die Eigenschaft durch eine
for...in
-Schleife aufgezählt werden kann. Siehe auch Aufzählbarkeit und Eigentum von Eigenschaften für Informationen darüber, wie Aufzählbarkeit mit anderen Funktionen und Syntaxen interagiert. configurable
-
Ein boolescher Wert, der anzeigt, ob die Eigenschaft gelöscht oder in eine Daten-Eigenschaft geändert werden kann und ob ihre Attribute geändert werden können.
Der Prototyp eines Objekts zeigt auf ein anderes Objekt oder auf null
— es ist konzeptionell eine versteckte Eigenschaft des Objekts, die üblicherweise als [[Prototype]]
dargestellt wird. Eigenschaften des Objekts [[Prototype]]
können auch auf dem Objekt selbst abgerufen werden.
Objekte sind temporäre Schlüssel-Wert-Paare, daher werden sie häufig als Karten verwendet. Es können jedoch ergonomische, Sicherheits- und Leistungsprobleme auftreten. Verwenden Sie ein Map
, um beliebige Daten zu speichern. Die Map
-Referenz enthält eine detailliertere Diskussion über die Vor- und Nachteile zwischen einfachen Objekten und Karten zur Speicherung von Schlüssel-Wert-Assoziationen.
Daten
Indexierte Sammlungen: Arrays und Typisierte Arrays
Arrays sind reguläre Objekte, bei denen eine bestimmte Beziehung zwischen integer-alternierenden Eigenschaften und der length
-Eigenschaft besteht.
Zusätzlich erben Arrays von Array.prototype
, das eine Handvoll bequemer Methoden zur Manipulation von Arrays bereitstellt. Zum Beispiel sucht indexOf()
einen Wert im Array und push()
hängt ein Element an das Array an. Dies macht Arrays zu einem perfekten Kandidaten, um geordnete Listen darzustellen.
Typisierte Arrays bieten eine array-ähnliche Ansicht eines zugrunde liegenden binären Datenpuffers und bieten viele Methoden, die ähnliche Semantiken wie die Array-Gegenstücke haben. "Typisierte Arrays" ist ein Oberbegriff für eine Reihe von Datenstrukturen, einschließlich Int8Array
, Float32Array
usw. Lesen Sie die Typisierte-Arrays-Seite für weitere Informationen. Typisierte Arrays werden häufig in Verbindung mit ArrayBuffer
und DataView
verwendet.
Schlüsselsammlungen: Maps, Sets, WeakMaps, WeakSets
Diese Datenstrukturen verwenden Objektverweise als Schlüssel. Set
und WeakSet
repräsentieren eine Sammlung eindeutiger Werte, während Map
und WeakMap
eine Sammlung von Schlüssel-Wert-Assoziationen darstellen.
Sie könnten Map
s und Set
s selbst implementieren. Da Objekte jedoch nicht verglichen werden können (im Sinne von "<" "kleiner als", zum Beispiel), und die Engine ihre Hash-Funktion für Objekte nicht offenlegt, würde die Suchleistung notwendigerweise linear sein. Native Implementierungen von ihnen (einschließlich WeakMap
s) können Suchleistungen haben, die etwa logarithmisch bis konstant sind.
Normalerweise könnte man, um Daten an einen DOM-Knoten zu binden, Eigenschaften direkt am Objekt festlegen oder data-*
-Attribute verwenden. Dies hat den Nachteil, dass die Daten für jedes Skript im selben Kontext verfügbar sind. Map
s und WeakMap
s machen es einfach, Daten privat an ein Objekt zu binden.
WeakMap
und WeakSet
erlauben das Speichern nur von garbage-collectierbaren Werten als Schlüssel, die entweder Objekte oder nicht registrierte Symbole sind, und die Schlüssel können selbst dann gesammelt werden, wenn sie sich noch in der Sammlung befinden. Sie werden speziell für Speicherverbrauchsoptimierung verwendet.
Strukturierte Daten: JSON
JSON (JavaScript Objekt Notation) ist ein leichtgewichtiges Datenformat zum Austausch von Daten, das aus JavaScript abgeleitet ist, aber von vielen Programmiersprachen verwendet wird. JSON baut universelle Datenstrukturen auf, die zwischen verschiedenen Umgebungen und sogar über Sprachgrenzen hinweg übertragen werden können. Siehe JSON
für weitere Details.
Weitere Objekte in der Standardbibliothek
JavaScript hat eine Standardbibliothek eingebauter Objekte. Lesen Sie die Referenz, um mehr über die eingebauten Objekte zu erfahren.
Typkonvertierung
Wie oben erwähnt, ist JavaScript eine schwach typisierte Sprache. Dies bedeutet, dass Sie oft einen Wert eines Typs verwenden können, wo ein anderer Typ erwartet wird, und die Sprache wird ihn für Sie in den richtigen Typ umwandeln. Dazu definiert JavaScript eine Handvoll von Konvertierungsregeln.
Primitive Konvertierung
Der primitive Konvertierungsprozess wird angewendet, wo ein primitiver Wert erwartet wird, aber es gibt keine starke Präferenz dafür, welcher tatsächliche Typ es sein sollte. Dies ist normalerweise der Fall, wenn ein String, eine Zahl oder ein BigInt gleichermaßen akzeptabel sind. Zum Beispiel:
- Der
Date()
-Konstruktor, wenn er ein Argument erhält, das keineDate
-Instanz ist — Strings repräsentieren Datumsstrings, während Numbers Zeitstempel darstellen. - Der
+
-Operator — wenn ein Operand ein String ist, wird eine String-Verkettung durchgeführt; andernfalls wird eine numerische Addition durchgeführt. - Der
==
-Operator — wenn ein Operand ein Primitive ist, während der andere ein Objekt ist, wird das Objekt in einen primitiven Wert ohne bevorzugten Typ konvertiert.
Diese Operation führt keine Konvertierung durch, wenn der Wert bereits ein Primitive ist. Objekte werden in Primitive konvertiert, indem ihre [Symbol.toPrimitive]()
(mit "default"
als Hinweis), valueOf()
, und toString()
-Methoden in dieser Reihenfolge aufgerufen werden. Beachten Sie, dass die primitive Konvertierung valueOf()
vor toString()
aufruft, was dem Verhalten der Zahlenkonvertierung ähnlich ist, sich jedoch von der Stringkonvertierung unterscheidet.
Die Methode [Symbol.toPrimitive]()
muss, falls vorhanden, ein Primitive zurückgeben — die Rückgabe eines Objekts führt zu einem TypeError
. Bei valueOf()
und toString()
, wenn eine ein Objekt zurückgibt, wird der Rückgabewert ignoriert und der Rückgabewert der anderen verwendet; wenn keiner vorhanden ist oder keiner ein Primitive zurückgibt, wird ein TypeError
geworfen. Zum Beispiel im folgenden Code:
console.log({} + []); // "[object Object]"
Weder {}
noch []
haben eine [Symbol.toPrimitive]()
-Methode. Sowohl {}
als auch []
erben valueOf()
von Object.prototype.valueOf
, die das Objekt selbst zurückgibt. Da der Rückgabewert ein Objekt ist, wird er ignoriert. Daher wird stattdessen toString()
aufgerufen. {}.toString()
gibt "[object Object]"
zurück, während [].toString()
""
zurückgibt, sodass das Ergebnis ihre Verkettung ist: "[object Object]"
.
Die Methode [Symbol.toPrimitive]()
hat immer Vorrang bei der Konvertierung in einen beliebigen primitiven Typ. Primitive Konvertierung verhält sich im Allgemeinen wie die Zahlenkonvertierung, da valueOf()
mit Priorität aufgerufen wird; jedoch können Objekte mit benutzerdefinierten [Symbol.toPrimitive]()
-Methoden jeden primitiven Wert zurückgeben. Date
und Symbol
-Objekte sind die einzigen eingebauten Objekte, die die [Symbol.toPrimitive]()
-Methode überschreiben. Date.prototype[Symbol.toPrimitive]()
behandelt den "default"
-Hinweis, als wäre es "string"
, während Symbol.prototype[Symbol.toPrimitive]()
den Hinweis ignoriert und immer ein Symbol zurückgibt.
Numerische Konvertierung
Es gibt zwei numerische Typen: Number und BigInt. Manchmal erwartet die Sprache speziell eine Zahl oder ein BigInt (wie Array.prototype.slice()
, wo der Index eine Zahl sein muss); andere Male kann sie beide akzeptieren und führt unterschiedliche Operationen abhängig vom Typ des Operanden durch. Für strikte Konvertierungsprozesse, die keine implizite Konvertierung vom anderen Typ zulassen, siehe Zahlenkonvertierung und BigInt-Konvertierung.
Numerische Konvertierung ist fast gleich wie Zahlenkonvertierung, außer dass BigInts unverändert zurückgegeben werden, anstatt einen TypeError
zu verursachen. Numerische Konvertierung wird von allen arithmetischen Operatoren verwendet, da sie sowohl für Zahlen als auch für BigInts überladen sind. Die einzige Ausnahme ist das unäre Plus, das immer eine Zahlenkonvertierung durchführt.
Andere Konvertierungen
Alle Datentypen, außer Null, Undefined und Symbol, haben ihre jeweiligen Konvertierungsprozesse. Siehe Stringkonvertierung, Boolesche Konvertierung, und Objektkonvertierung für weitere Details.
Wie Sie vielleicht bemerkt haben, gibt es drei unterschiedliche Pfade, durch die Objekte in Primitive konvertiert werden können:
- Primitive Konvertierung:
[Symbol.toPrimitive]("default")
→valueOf()
→toString()
- Numerische Konvertierung, Zahlenkonvertierung, BigInt-Konvertierung:
[Symbol.toPrimitive]("number")
→valueOf()
→toString()
- Stringkonvertierung:
[Symbol.toPrimitive]("string")
→toString()
→valueOf()
In allen Fällen muss [Symbol.toPrimitive]()
, wenn vorhanden, aufrufbar sein und ein Primitive zurückgeben, während valueOf
oder toString
ignoriert werden, wenn sie nicht aufrufbar sind oder ein Objekt zurückgeben. Am Ende des Prozesses, wenn erfolgreich, ist das Ergebnis garantiert ein Primitive. Das resultierende Primitive unterliegt dann weiteren Konvertierungen, abhängig vom Kontext.
Siehe auch
- JavaScript-Datenstrukturen und-Algorithmen von Oleksii Trekhleb
- Informatik in JavaScript von Nicholas C. Zakas