Was ist der Unterschied zwischen String (Wert) und value.toString ()

103

Javascript hat viele "Tricks" in Bezug auf Typen und Typkonvertierungen. Ich frage mich also, ob diese beiden Methoden gleich sind oder ob es einen Eckfall gibt, der sie unterscheidet.

AlfaTeK
quelle

Antworten:

121

Sie sind nicht vollständig identisch, und tatsächlich ruft der als Funktion aufgerufene String-Konstruktor (Ihr erstes Beispiel) am Ende die toStringMethode des übergebenen Objekts auf, zum Beispiel:

var o = { toString: function () { return "foo"; } };
String(o); // "foo"

Wenn sich ein Bezeichner hingegen auf nulloder bezieht undefinedund Sie die toStringMethode nicht verwenden können , gibt es eine TypeErrorAusnahme :

var value = null;
String(null);     // "null"
value.toString(); // TypeError

Der Stringals Funktion aufgerufene Konstruktor entspricht in etwa:

value + '';

Die Typkonvertierungsregeln von Object- to- Primitive werden in der Spezifikation, der [[DefaultValue]]internen Operation, ausführlich beschrieben .

Kurz zusammengefasst werden beim Konvertieren von Object- to- String die folgenden Schritte ausgeführt:

  1. Falls verfügbar, führen Sie die toStringMethode aus.
    • Wenn das resultein Grundelement ist , kehren Sie zurück result, andernfalls fahren Sie mit Schritt 2 fort.
  2. Falls verfügbar, führen Sie die valueOfMethode aus.
    • Wenn das resultein Grundelement ist , kehren Sie zurück result, andernfalls fahren Sie mit Schritt 3 fort.
  3. Werfen TypeError.

In Anbetracht der obigen Regeln können wir ein Beispiel für die Semantik geben:

var o = {
  toString: function () { return "foo"; },
  valueOf:  function () { return "bar"; }
};

String(o); // "foo"

// Make the toString method unavailable:
o.toString = null;

String(o); // "bar"

// Also make the valueOf method unavailable:
o.valueOf = null;

try { 
  String(o); 
} catch (e) {
  alert(e); // TypeError
}

Wenn Sie mehr über diesen Mechanismus erfahren möchten, würde ich empfehlen, sich die ToPrimitiveund die ToStringinternen Operationen anzusehen.

Ich empfehle auch, diesen Artikel zu lesen:

CMS
quelle
1
Wenn Sie dies aufrufen, gibt es einen dritten "Weg": Bei new String(value)jedem Wert wird immer ein Zeichenfolgenobjekt zurückgegeben.
Herbertusz
@Herbertusz new String({toString: null})wirft a TypeError.
10онстантин Ван
Mit dem Hinzufügen von Symbolen String()und haben + ''jetzt einen ziemlich signifikanten Unterschied. String(Symbol())wird ausgeführt, aber Symbol() + ''wird einen Fehler auslösen (und Symbol () wird im Gegensatz zu null und undefiniert einen Falsey Guard passieren, x && (x + '')kann also jetzt werfen).
Yeerk
24

value.toString()wird einen Fehler verursachen, wenn valuenull ist. String(value)sollte nicht.

Beispielsweise:

var value = null;
alert(value.toString());

wird scheitern, weil value == null.

var value = null;
alert(String(value));

sollte eine Meldung mit der Aufschrift "null" (oder ähnlich) anzeigen, die jedoch nicht abstürzt.

Jonathan
quelle
3
Ich habe noch nie eine Nullzeiger-Ausnahme in Javascript gesehen ... wo haben Sie das gesehen?
Dagg Nabbit
nett. Mit einem Beispiel wäre es noch schöner
Mykhal
@no, @casablanca Behoben. Ich bin an Java gewöhnt. @mykhal Wie sieht das aus?
Jonathan
Es gibt eine Zeichenfolge "null" zurück :)
moefinley
1

String(value)sollte das gleiche Ergebnis wie value.toString()in jedem Fall haben, außer für Werte ohne Eigenschaften wie nulloder undefined. ''+valuewird das gleiche Ergebnis produzieren.

Dagg Nabbit
quelle
1

String () [der Konstruktoraufruf ] ruft grundsätzlich .toString () auf

.toString () und String () können für primitive Werte (number, boolean, string) aufgerufen werden und bewirken im Grunde nichts Besonderes:

true => 'true'

false => 'false'

17 => '17'

'hallo' => 'hallo'

Beim Aufrufen dieser Funktionen für Objekte wird es jedoch interessant:

Wenn das Objekt über eine eigene .toString () -Funktion verfügt, wird es immer dann aufgerufen, wenn dieses Objekt (explizit / implizit) als Zeichenfolge behandelt werden soll.

let obj = {
           myName:"some object",
           toString:function(){ return this.myName; } 
          }

//implicitly treating this obj as a string
"hello " + obj; //"hello some object"

//OR (explicitly)
"hello " + String(obj) //calling the existent toString function

//OR
"hello " + obj.toString(); //calling toString directly

Übrigens, wenn Sie dieses Objekt als Zahl behandeln möchten, sollte darin eine .valueOf () -Funktion definiert sein.

Was ist, wenn wir beide in einem Objekt haben?

wenn wir dieses Objekt als String behandeln wollen => benutze .toString ()

wenn wir dieses Objekt als Zahl behandeln wollen => benutze .valueOf ()

Was ist, wenn wir nur .valueOf () definiert haben?

.valueOf (), das im Objekt definiert ist, wird aufgerufen, unabhängig davon, ob das Objekt als Zeichenfolge oder als Zahl behandelt werden soll

Louay Alosh
quelle