Wann ist eine JavaScript-Zeichenfolge keine Zeichenfolge? [Duplikat]

8

Über hier habe ich den Ratschlag gefunden, dass es am besten ist zu verwenden Nicht-Typ-Zwangsstring-Vergleich, aber in Chrome entdeckte ich etwas seltsam:

%Vor%

Ist das Standardverhalten? Wenn ja, welche Art von t1 und t2 gibt es? Danke.

    
Nathan Andrew Mullenax 15.08.2012, 21:19
quelle

6 Antworten

5

String , aufgerufen als Funktion, konvertiert sein Argument in ein string . String , als Konstruktor bezeichnet, erstellt ein Objekt, dessen Prototyp die Funktion String ist. (Überprüfen Sie die James-Antwort für den entsprechenden ECMAScript-Spezifikationsabschnitt.)

Das ist in der Tat verwirrend.

Die zwei Gleichheitsoperatoren machen tatsächlich sehr unterschiedliche Dinge. Aus dem Dokument ECMA-262, v 5.1 , macht === :

  
  1. Wenn Type(x) sich von Type(y) unterscheidet, geben Sie false zurück.
  2.   
  3. Wenn Type(x) Undefined ist, geben Sie true zurück.
  4.   
  5. Wenn Type(x) Null ist, geben Sie true .
  6. zurück   
  7. Wenn Type(x) Number ist, dann
          ein. Wenn x ist NaN , gib false zurück.
          b. Wenn y ist NaN , gib false zurück.
          c. Wenn x der gleiche Number -Wert ist wie y , geben Sie true zurück.
          d. Wenn x ist +0 und y ist -0 , geben Sie true zurück.
          e. Wenn x ist -0 und y ist +0 , geben Sie true zurück.
          f. Rückgabe false .
  8.   
  9. Wenn Type(x) String ist, dann gebe true zurück, wenn x und y genau die gleiche Zeichenfolge sind (gleiche Länge und gleiche Zeichen in den entsprechenden Positionen); Andernfalls geben Sie false .
  10. zurück   
  11. Wenn Type(x) Boolean ist, geben Sie true zurück, wenn x und y beide true oder beide false sind; Andernfalls geben Sie false .
  12. zurück   
  13. Gibt true zurück, wenn sich x und y auf dasselbe Objekt beziehen. Andernfalls gib false .
  14. zurück   

Während == tut:

  
  1. Wenn Type(x) dasselbe ist wie Type(y) , dann
      ein. Wenn Type(x) ist Undefined , gib true zurück.
      b. Wenn Type(x) ist Null , gib true zurück.
      c. Wenn Type(x) Number ist, dann
      ich. Wenn x ist NaN , gib false zurück.
      ii. Wenn y ist NaN , gib false zurück.
      iii. Wenn x der gleiche Number -Wert ist wie y , geben Sie true zurück.
      iv. Wenn x ist +0 und y ist -0 , geben Sie true zurück.
      v. Wenn x ist -0 und y ist +0 , geben Sie true zurück.
      vi. Rückgabe false .
      d. Wenn Type(x) String ist, dann gebe true zurück, wenn x und y genau die gleiche Zeichenfolge haben (gleiche Länge und gleiche Zeichen in den entsprechenden Positionen). Andernfalls gib false zurück.
      e. Wenn Type(x) ist Boolean , geben Sie true zurück, wenn x und y beide true oder beide false sind. Andernfalls gib false zurück.
      f. Gibt true zurück, wenn sich x und y auf dasselbe Objekt beziehen. Andernfalls gib false .
  2. zurück   
  3. Wenn x null ist und y nicht definiert ist, geben Sie true zurück.
  4.   
  5. Wenn x nicht definiert ist und y null ist, geben Sie true zurück.
  6.   
  7. Wenn Type(x) ist Number und Type(y) ist String , geben Sie das Ergebnis des Vergleichs
    x == ToNumber(y) zurück.
  8.   
  9. Wenn Type(x) ist String und Type(y) ist Number , geben Sie das Ergebnis des Vergleichs
    ToNumber(x) == y zurück.
  10.   
  11. Wenn Type(x) ist Boolean , gebe das Ergebnis des Vergleichs ToNumber(x) == y zurück.
  12.   
  13. Wenn Type(y) ist Boolean , gebe das Ergebnis des Vergleichs x == ToNumber(y) zurück.
  14.   
  15. Wenn Type(x) entweder String oder Number und Type(y) ist Object , geben Sie das Ergebnis des Vergleichs x == ToPrimitive(y) zurück.
  16.   
  17. Wenn Type(x) ist Object und Type(y) ist entweder String oder Number , geben Sie das Ergebnis des Vergleichs ToPrimitive(x) == y zurück.
  18.   
  19. Gibt false zurück.
  20.   

Beachten Sie, dass in der Spezifikation das Type eines primitiven Zeichenfolgenobjekts String ist, während der Typ eines Objekts (einschließlich des String -Objekts) Object ist.

Bei === ist die relevante Zeile #1 : Die Type der Objekte sind unterschiedlich, daher wird false zurückgegeben.

Bei == ist die relevante Zeile #8 : x ist ein String ( "Hello world!" ) und y ist ein Object (Das String -Objekt enthält die Zeichenkette "Hello world!" ) . Somit wird der Vergleich x == ToPrimitive(y) gemacht. ToPrimitive endet mit dem Aufruf der Methode valueOf des Objekts oder, falls diese Methode nicht existiert, der Methode toString . In diesem Fall gibt die Methode String von valueOf -Objekt das Grundelement string zurück, das das Objekt enthält. Daher wird die Gleichheitsoperation erneut ausgeführt, diesmal zwischen zwei Grundelementen string s, die denselben Text enthalten, der true dank #1.d zurückgibt.

JavaScript ist ein bisschen unordentlich unter der Haube ...

BEARBEITEN: Beachten Sie, dass beim Vergleich von zwei Objekten keine Konvertierungen vorgenommen werden, sondern die Regel #1.f . Dank der Spezifikation konnte ich die Ausgabe des folgenden Codes korrekt vorhersagen:

%Vor%

EDIT: Nur gedacht, ich würde hinzufügen, dass diese Unterschiede noch mehr durch implizite Typumwandlung verwischt werden. Zum Beispiel funktioniert das Folgende:

%Vor%

Das liegt aber nicht daran, dass "hi" ein Objekt ist (wie in Python):

%Vor%

Sondern weil . operator führt eine Konvertierung vom Primitiven durch string type zum String Object type (erzeugt ein neues String-Objekt), dessen toString -Methode dann aufgerufen wird.

    
Claudiu 15.08.2012, 21:23
quelle
9

Wenn Sie das Schlüsselwort " new " nicht mit String verwenden, erhalten Sie eine primitive Zeichenfolge.

Wenn Sie das Schlüsselwort " new " verwenden, erhalten Sie ein String-Objekt anstelle eines Primitivs.

Wenn Sie == verwenden, wird versucht, in einen vergleichbaren Typ zu konvertieren, damit er gleich sein kann.

Wenn Sie === verwenden, wird es nicht konvertiert, sodass ein Objekt nicht einem Primitiv entsprechen kann.

    
gray state is coming 15.08.2012 21:23
quelle
5

Hier ist die Erklärung

%Vor%

Und:

%Vor%

Wenn Sie === verwenden, wird auf den Typ geachtet, so dass false

zurückgegeben wird     
Ibu 15.08.2012 21:23
quelle
3

Dieses Verhalten wird in der ECMAScript 5-Spezifikation 15.5.1 und 15.5.2 erläutert:

  

Wenn String als Funktion und nicht als Konstruktor aufgerufen wird, führt es eine Typkonvertierung durch.

     

...

     

Gibt einen String-Wert (nicht ein String -Objekt) zurück, der von ToString(value) berechnet wurde. Wenn value nicht angegeben wird, wird die leere Zeichenfolge "" zurückgegeben.

So String("some string") erstellt einen String-Wert.

  

Wenn String als Teil eines new -Ausdrucks aufgerufen wird, handelt es sich um einen Konstruktor: Er initialisiert das neu erstellte Objekt.

So erstellt new String("some string") eine Instanz des Objekts String .

Und um Ihre Fragen zu beantworten:

  

Ist das Standardverhalten?

Ja , aus den oben genannten Gründen.

  

Wenn ja, was sind die jeweiligen Typen von t1 und t2

?

Sie können dies mit dem Operator typeof überprüfen:

%Vor%     
James Allardice 15.08.2012 21:27
quelle
1

Dies geschieht, weil der Operator == nur prüft, ob die Werte identisch sind, während === sowohl den Wert als auch den -Typ überprüft. new String("Hello world!") erhält nicht den Typ string , es ist ein object , während String("Hello world!") eigentlich ein string ist.

    
Chris Clower 15.08.2012 21:24
quelle
0

Das erste Beispiel String("Hello world!)" erstellt eine primitive Zeichenfolge, während das zweite Beispiel new String("Hello world!") ein String-Objekt erstellt.

    
Ivan 15.08.2012 21:23
quelle

Tags und Links