2012-06-08 22 views
97

miałem zamiar rozpocząć korzystanie === (potrójne równymi ścisłe porównanie) cały czas przy porównywaniu wartości ciągów, ale teraz uważam, żeDlaczego ("foo" === nowy ciąg ("foo")) ocenia na false w JavaScript?

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

jest fałszywa, a sama z tym:

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

przedmiotu:

f == g; // true 

Więc jest to zalecane, aby zawsze używać == dla porównania ciągów, lub zawsze konwertować zmienne ciągi przed porównaniem?

+4

Może dlatego 'foo' jest czysty łańcuch i' new String ("foo") 'jest Obiekt String –

+0

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

+6

Zaleca się, aby nie tworzyć ciągów z 'nowym ciągiem' (całkowicie bezcelowe) zamiast używając '==' – Esailija

Odpowiedz

124

"foo" to ciąg pierwotny prymitywny. (ta koncepcja nie istnieje w języku C# lub Java)

new String("foo") to obiekt w ramkach.

Operator ===behaves differently on primitives and objects.
Porównując prymitywy (tego samego typu), === zwróci wartość true, jeśli obie mają tę samą wartość.

Porównując obiekty, === zwróci true tylko wtedy, gdy odnoszą się do tego samego obiektu (porównywanie przez odniesienie). Tak więc, new String("a") !== new String("a").

W twoim przypadku === zwraca wartość false, ponieważ operandy są różnych typów (jeden jest prymitywny, a drugi jest obiektem).


Primenty nie są wcale obiektami.
Operator typeof nie zwróci "object" dla elementów pierwotnych.

Podczas próby uzyskania dostępu do właściwości obiektu pierwotnego (używając go jako obiektu), język JavaScript spowoduje umieszczenie go w obiekcie, tworząc za każdym razem nowy obiekt. Jest to opisane w specification.

To dlaczego nie można umieścić na właściwości prymitywów:

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

każdym razem piszesz x.property, A inny zapakowane String obiekt jest tworzony.

+32

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

+1

Interesujące, myślałem, że ciągi były obiektami w JS. – ddlshack

+0

@ddlshack: Wszystko może być nawet ciągiem znaków obiektu, jeśli utworzysz w nim instancję. – Sarfraz

4

foo jest czysty łańcuch i new String("foo") jest String Object

34

Korzystanie ===,

  • obiekt jest równy nigdy do niczego innego poza odniesieniem do siebie.

  • prymityw jest równy w porównaniu z innym prymitywem, jeśli jego typ i wartość są takie same.

+3

'new String (" foo ") === new String (" foo ")' jest 'false' :-P –

+11

@Rocket: Dokładnie o to mi chodzi. –

+5

@Rocket: powinno być, ponieważ są to dwa różne odniesienia ... –

10

new słowo jest przestępcą tutaj (jak zwykle, mogę powiedzieć) ...

Podczas korzystania new, jawnie wyrazić swoją chęć do pracy z obiektu. To może być zaskakujące dla ciebie, ale:

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

... daje potężny false. To proste: porównywane nie są obiekty wewnątrz obiektów, ale odniesienia obiektów. I oczywiście nie są równe, ponieważ powstały dwa różne przedmioty.

Co prawdopodobnie chcesz użyć jest konwersja:

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

... i że da wam, jak się spodziewano, true jako rezultat, dzięki czemu można cieszyć się i rozwijać z równym foos zawsze.)

+2

szybkie pytanie na temat korzystania z tego. Dzwonisz do String (konstruktora?) Bez słowa kluczowego "new". Czy to nie oznacza, że ​​zanieczyścisz zakres dowolnymi właściwościami przypisanymi do konstruktora String? Czy to się nie dzieje, ponieważ konstruktor jest natywnym kodem? Innymi słowy, załóżmy, że funkcja String zawierała "this.a = 1;" - to znaczy, że twoja funkcja/obiekt miałaby teraz własność a = 1. –

+0

Przypuszczam (ale nie mogę powiedzieć na pewno), że każda z funkcji "konstruktora boksu" najpierw sprawdza jego kontekst - a jeśli nie jest "nowsza" (tj. obiekt prototypowy), natychmiast przełącza się na metodę konwersji. W przypadku String, który byłby na przykład metodą 'toString()'. – raina77ow

2

Z node.js REPL ("węzeł" w linii poleceń, jeśli jest zainstalowany):

> "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'
Powiązane problemy