Signatur
Beschreibung
Symbol.toPrimitive ist eine statische, schreibgeschützte Dateneigenschaft von Symbol und enthält eines der sogenannten bekannten Symbole (well-known symbols). Legt ein Objekt unter diesem Schlüssel eine Methode ab, ruft die JavaScript-Engine sie immer dann auf, wenn das Objekt in einen primitiven Wert umgewandelt werden muss, etwa bei +obj, `${obj}`, obj + "", obj == 5 oder String(obj).
Die Methode bekommt einen Hinweis (hint) als Zeichenkette mit, an dem sie erkennt, welcher Zieltyp erwartet wird: "number" (z. B. bei arithmetischen Operationen, Number() und Vergleichen mit </>), "string" (z. B. bei Template-Literalen, String() und Eigenschaftsschlüsseln) oder "default" (bei binärem + und bei ==). Ist die Methode vorhanden, hat sie Vorrang vor valueOf() und toString(). Diese beiden werden dann nicht mehr für die Umwandlung herangezogen.
Einsatzgebiete sind Wertobjekte wie Geldbeträge, Maßeinheiten oder Zeitangaben, die sich in Rechnungen wie Zahlen und in Textausgaben wie formatierte Zeichenketten verhalten sollen. In der Standardbibliothek setzen Date.prototype[Symbol.toPrimitive] und Symbol.prototype[Symbol.toPrimitive] dieses Symbol bereits ein.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $hint Pflicht | "number" | "string" | "default" | Wird von der Engine an die Methode [Symbol.toPrimitive](hint) übergeben und gibt an, welcher primitive Typ bevorzugt wird. Symbol.toPrimitive selbst hat keine Parameter. |
Rückgabewert
Symbol.toPrimitive. Die unter diesem Schlüssel hinterlegte Methode muss einen primitiven Wert zurückgeben (string, number, bigint, boolean, symbol, null oder undefined).Beispiele
Welcher Hinweis kommt wann an?
const obj = {
[Symbol.toPrimitive](hint) {
console.log('hint:', hint);
if (hint === 'number') return 42;
if (hint === 'string') return 'zweiundvierzig';
return 'default';
}
};
console.log(+obj); // number
console.log(`${obj}`); // string
console.log(obj + ''); // default
console.log(obj == 'default'); // default
Geldbetrag-Klasse: rechnen und formatiert ausgeben
class Money {
constructor(cents, currency = 'EUR') {
this.cents = cents;
this.currency = currency;
}
[Symbol.toPrimitive](hint) {
if (hint === 'string') {
return new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: this.currency
}).format(this.cents / 100);
}
// 'number' und 'default' liefern den Betrag in Euro
return this.cents / 100;
}
}
const preis = new Money(1999);
const versand = new Money(495);
console.log(preis + versand); // Rechnen
console.log(`Preis: ${preis}`); // Anzeige
console.log(preis > versand); // Vergleich
Vorrang vor valueOf() und toString()
const temp = {
valueOf: () => 1,
toString: () => 'eins',
[Symbol.toPrimitive]: (hint) => (hint === 'string' ? 'Symbol-String' : 99)
};
console.log(temp * 2);
console.log(String(temp));
Eingebautes Verhalten von Date
const d = new Date(0);
console.log(typeof d[Symbol.toPrimitive]);
console.log(d[Symbol.toPrimitive]('number'));
// Date behandelt 'default' wie 'string'
console.log(typeof (d + 1));
// Wichtig · Fallstricke
- Rückgabewert muss primitiv sein: Gibt die Methode ein Objekt zurück, wirft die Engine einen
TypeError(„Cannot convert object to primitive value“). - Kein Rückgriff auf valueOf/toString: Ist
[Symbol.toPrimitive]definiert, ruft die EnginevalueOf()undtoString()für die Umwandlung nicht mehr auf. Alle drei Hinweise sollten deshalb sinnvoll behandelt werden. - Ist der Wert unter dem Schlüssel weder
undefinednochnullnoch eine Funktion, wirft die Engine ebenfalls einenTypeError. - Der Hinweis
"default"kommt bei binärem+und bei==an. Hier ist oft nicht klar, ob addiert oder verkettet werden soll. Deshalb sollte ein Objekt dafür eine eindeutige Konvention festlegen. - Die strikte Gleichheit
===löst keine Umwandlung aus und ruft die Methode daher nie auf. - Die Eigenschaft selbst ist nicht beschreibbar, nicht aufzählbar und nicht konfigurierbar.
- Kompatibilität: ES2015, wird von allen modernen Browsern und von Node.js ab 6 unterstützt. Im Internet Explorer fehlt die Unterstützung.