Warum wird ("foo" === neuer String ("foo")) in JavaScript als falsch ausgewertet?

98

Ich wollte die ganze Zeit === (Triple Equals, strenger Vergleich) verwenden, wenn ich String-Werte vergleiche, aber jetzt finde ich das

"foo" === new String("foo")

ist falsch und dasselbe damit:

var f = "foo", g = new String("foo");
f === g; // false

Natürlich:

f == g; // true

Wird also empfohlen, immer == für den Zeichenfolgenvergleich zu verwenden oder Variablen vor dem Vergleich immer in Zeichenfolgen zu konvertieren?

Michael Butler
quelle
6
Vielleicht, weil fooes die reine Zeichenfolge und new String("foo")die Objektzeichenfolge ist
Danilo Valente
6
Es wird empfohlen, keine Zeichenfolgen mit new String(völlig sinnlos) zu erstellen, anstatt sie zu verwenden==
Esailija
2
Warum sollte jemand überhaupt ein Konstrukt wie new String("foo")in Javascript verwenden wollen ? Ich habe noch nie einen solchen Code im Code gesehen, dh jQuery ...
Robert Koritnik
2
Sie können String(obj)eine Box-Zeichenfolge in das Grundelement konvertieren, sobald Sie Ihren Parameter "Zeichenfolge" erhalten haben. ("foo" === String(new String("foo"))) === true
OrangeDog

Antworten:

126

"foo"ist ein String- Primitiv . (Dieses Konzept existiert nicht in C # oder Java)

new String("foo") ist ein Boxed-String-Objekt.

Der ===Operator verhält sich bei Grundelementen und Objekten unterschiedlich .
Beim Vergleich von Grundelementen (desselben Typs) ===wird true zurückgegeben, wenn beide denselben Wert haben.

Wird beim Vergleichen von Objekten ===nur dann true zurückgegeben, wenn sie sich auf dasselbe Objekt beziehen (Vergleich nach Referenz). Also , new String("a") !== new String("a").

In Ihrem Fall wird ===false zurückgegeben, da die Operanden unterschiedlichen Typs sind (einer ist ein Grundelement und der andere ein Objekt).


Primitive sind überhaupt keine Objekte.
Der typeofOperator wird nicht "object"für Grundelemente zurückkehren.

Wenn Sie versuchen, auf eine Eigenschaft eines Grundelements zuzugreifen (indem Sie es als Objekt verwenden), wird es von der Javascript-Sprache in ein Objekt eingefügt und jedes Mal ein neues Objekt erstellt. Dies ist in der Spezifikation beschrieben .

Aus diesem Grund können Sie Primitiven keine Eigenschaften zuweisen:

var x = "a";
x.property = 2;
alert(x.property) //undefined

Jedes Mal, wenn Sie schreiben x.property, wird ein anderes Boxobjekt Stringerstellt.

SLaks
quelle
33
+1 typeof "foo"; // "string",typeof new String("foo"); // "object"
Sampson
1
Interessant, ich dachte, Strings wären Objekte in JS.
Cameron Martin
1
@Sarfraz: Fast alles. Vergiss nicht nullund undefined.
2
if( Object(a) !== a ) { //it's a primitive }
Esailija
1
Java haben Primitive / .Net nicht
Marcelo De Zen
34

Verwenden von ===,

  • Ein Objekt ist niemals gleich etwas anderem als einem anderen Verweis auf sich selbst.

  • Ein Grundelement ist im Vergleich zu einem anderen Grundelement gleich, wenn Typ und Wert gleich sind.


quelle
3
new String("foo") === new String("foo")ist false:-P
Rocket Hazmat
10

Das newWort ist hier ein Verbrecher ( wie üblich , darf ich sagen) ...

Wenn Sie verwenden new, drücken Sie ausdrücklich Ihren Wunsch aus, mit Objekten zu arbeiten . Es mag für Sie überraschend sein, aber dies:

var x = new String('foo');
var y = new String('foo');
x === y; 

... wird dir einen mächtigen geben false. Es ist ganz einfach: Im Vergleich werden nicht die Innenseiten der Objekte, sondern die Referenzen der Objekte verglichen. Und sie sind natürlich nicht gleich, da zwei verschiedene Objekte erstellt wurden.

Was Sie wahrscheinlich verwenden möchten, ist die Konvertierung :

var x = String('foo');
var y = String('foo');
x === y;

... und das wird Ihnen erwartungsgemäß truedas Ergebnis geben, damit Sie sich für immer freuen und mit Ihrem Gleichen gedeihen können foos. )

raina77ow
quelle
2
kurze Frage dazu. Sie rufen String (einen Konstruktor?) Ohne das Schlüsselwort 'new' auf. Bedeutet dies nicht, dass Sie den Bereich mit Eigenschaften verschmutzen, die im String-Konstruktor zugewiesen sind? Oder passiert das nicht, weil der Konstruktor nativer Code ist? Mit anderen Worten, nehmen wir an, die String-Funktion enthielt "this.a = 1;" - Das bedeutet, dass Ihre Funktion / Ihr Objekt jetzt eine Eigenschaft a = 1 haben würde.
Michael Butler
Ich nehme an (kann aber nicht sicher sagen), dass jede der Funktionen des 'Boxkonstruktors' zuerst ihren Kontext überprüft - und wenn es sich nicht um eine 'neue' Funktion (dh ein Prototypobjekt) handelt, wechselt sie sofort zur Konvertierungsmethode. Im Fall von String wäre dies toString()beispielsweise eine Methode.
raina77ow
4

fooist die reine Zeichenfolge und new String("foo")ist die Objektzeichenfolge

Danilo Valente
quelle
2

Aus der Datei node.js REPL ("Knoten" in der Befehlszeile, falls installiert):

> "foo" === (new String("foo")).valueOf()
true
> "foo" === new String("foo")
false
> typeof("foo")
'string'
> typeof(new String("foo"))
'object'
> typeof((new String("foo")).valueOf())
'string'
mda
quelle