2012-06-08 8 views
97

Ich wollte === (triple Gleichen, strenger Vergleich) die ganze Zeit, wenn String-Werte zu vergleichen, beginnen, aber ich finde jetzt, dassWarum wird ("foo" === new String ("foo")) in JavaScript als false ausgewertet?

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

falsch ist, und gleiche mit diesem:

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

natürlich:

f == g; // true 

So ist es empfehlenswert, immer == für String-Vergleich zu verwenden, oder immer Variablen in Strings umwandeln, vor dem Vergleich?

+4

Vielleicht, weil 'foo' ist der reine String und 'new String ("foo")' ist die Objektkette –

+0

Hintergrund: http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript –

+6

Es wird empfohlen, keine Strings mit 'new String' (völlig sinnlos) zu erstellen using '==' – Esailija

Antwort

124

"foo" ist eine Zeichenfolge primitive. (Dieses Konzept existiert nicht in C# oder Java)

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

Der Operator ===behaves differently on primitives and objects.
Beim Vergleich von Primitiven (desselben Typs) gibt === den Wert true zurück, wenn beide den gleichen Wert haben.

Beim Vergleich von Objekten gibt === nur dann true zurück, wenn sie sich auf dasselbe Objekt beziehen (Vergleich durch Referenz). So, new String("a") !== new String("a").

In Ihrem Fall gibt === false zurück, weil die Operanden von verschiedenen Typen sind (einer ist ein Primitiv und der andere ist ein Objekt).


Primitive sind überhaupt keine Objekte.
Der Operator typeof gibt "object" für Primitive nicht zurück.

Wenn Sie versuchen, auf eine Eigenschaft eines Primitivs zuzugreifen (indem Sie es als Objekt verwenden), wird es von der JavaScript-Sprache in ein Objekt eingeschlossen und jedes Mal ein neues Objekt erstellt. Dies ist in der specification beschrieben. Diese

ist, warum Sie nicht Eigenschaften auf Primitiven setzen können:

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

Jedes Mal, wenn Sie x.property, ein verschiedenen boxed String Objekt schreiben wird erstellt.

+32

+1 'typeof" foo "; // "string" ',' typeof new String ("foo"); // "object" ' – Sampson

+1

Interessant, ich dachte Strings waren Objekte in JS. – ddlshack

+0

@ ddlshack: Alles kann ein Objekt sein, sogar eine Zeichenkette, wenn Sie in einer Instanz davon erstellen. – Sarfraz

4

foo ist die reine String und new String("foo") ist das Objekt String

34

=== Verwendung,

  • ein Objekt ist nie gleich etwas anderes als eine andere Referenz auf sich selbst.

  • Ein Primitiv ist gleich, wenn es mit einem anderen Primitiv verglichen wird, wenn Typ und Wert identisch sind.

+3

'neuer String (" foo ") === neuer String (" foo ")' ist 'false' :-P –

+11

@Rocket: Exacly mein Punkt. –

+5

@Rocket: sollte sein, da sie zwei verschiedene Referenzen sind ... –

10

Das new Wort ist ein Verbrecher hier (wie üblich, kann ich sagen) ...

Wenn Sie new, Sie ausdrücklich Ihr Wunsch, mit Objekt arbeiten auszudrücken. Es könnte sein, überraschend für Sie, aber dies:

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

... geben Ihnen einen mächtigen false. Es ist einfach: Vergleicht man nicht die Objekte, sondern die Referenzen der Objekte. Und sie sind natürlich nicht gleich, da zwei verschiedene Objekte geschaffen wurden.

Was möchten Sie wahrscheinlich verwenden ist Umwandlung:

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

... und das wird Ihnen, wie erwartet, true als Ergebnis, so dass Sie mit Ihrem gleich foos immer freuen und gedeihen.

)
+2

schnelle Frage zur Verwendung dieser. Sie rufen String (einen Konstruktor?) Ohne das Schlüsselwort 'new' auf. Bedeutet das nicht, dass Sie den Gültigkeitsbereich mit Eigenschaften, die innerhalb des Konstruktors String zugewiesen sind, verschmutzen werden? Oder passiert das nicht, weil der Konstruktor nativer Code ist? Mit anderen Worten, angenommen, die String-Funktion enthält "this.a = 1;" - Das heißt, Ihre Funktion/Ihr Objekt hätte jetzt eine Eigenschaft a = 1. –

+0

Ich nehme an (aber ich kann nicht mit Sicherheit sagen), jede der Funktionen des Boxkonstruktors prüft zunächst ihren Kontext - und wenn es kein "neuer" ist (dh ein Prototyp-Objekt), wechselt sofort zur Konvertierungsmethode. Im Fall von String zum Beispiel die Methode toString(). – raina77ow

2

Vom node.js REPL ("Knoten" auf der Kommandozeile installiert if):

> "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'
Verwandte Themen