JavaScript'te ("foo" === new String ("foo")) neden yanlış olarak değerlendirilir?


98

Dize değerlerini karşılaştırırken her zaman === (üçlü eşittir, kesin karşılaştırma) kullanmaya başlayacaktım, ama şimdi bunu buldum

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

yanlıştır ve bununla aynıdır:

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

Elbette:

f == g; // true

Öyleyse, dize karşılaştırması için her zaman == kullanmanız veya karşılaştırmadan önce değişkenleri dizelere dönüştürmeniz önerilir mi?


6
Belki foode saf dizge ve new String("foo")Nesne Dizesi olduğu için
Danilo Valente


6
Kullanmak new Stringyerine (Tamamen anlamsız) ile dizeler oluşturmamanız önerilir==
Esailija

2
Neden herkes new String("foo")ilk başta Javascript'teki gibi yapıyı kullanmak istesin ?
Kodda

2
String(obj)"Dize" parametrenizi aldıktan sonra, kutulu bir dizeyi ilkele dönüştürmek için kullanabilirsiniz . ("foo" === String(new String("foo"))) === true
OrangeDog

Yanıtlar:


126

"foo"ilkel bir dizedir . (bu kavram C # veya Java'da mevcut değildir)

new String("foo") kutulu dize nesnesidir.

===Operatör ilkel ve nesneler üzerinde farklı davranır .
İlkelleri karşılaştırırken (aynı türden), ===ikisi de aynı değere sahipse doğru sonucunu döndürür.

Nesneleri karşılaştırırken, ===yalnızca aynı nesneye atıfta bulunuyorlarsa (başvuruya göre karşılaştırma) true döndürür. Böylece new String("a") !== new String("a").

Sizin durumunuzda, ===işlenenler farklı türlerde olduğundan (biri ilkel, diğeri bir nesnedir) false döndürür.


İlkel öğeler hiç de nesne değildir. Operatör döndürmez öncülleri için.
typeof"object"

Bir ilkelin bir özelliğine erişmeye çalıştığınızda (onu bir nesne olarak kullanarak), Javascript dili onu bir nesneye yerleştirir ve her seferinde yeni bir nesne oluşturur. Bu, spesifikasyonda açıklanmaktadır .

Bu nedenle, ilkellere özellikler koyamazsınız:

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

Her yazışınızda x.property, farklı bir kutulu Stringnesne oluşturulur.


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

1
İlginç, dizelerin JS'de nesneler olduğunu düşündüm.
Cameron Martin

1
@Sarfraz: Neredeyse her şey. Unutma nullve undefined.

2
if( Object(a) !== a ) { //it's a primitive }
Esailija

1
Java'da ilkel / .Net yok
Marcelo De Zen

34

Kullanarak ===,

  • Bir Nesne, kendisine yapılan başka bir referans dışında asla hiçbir şeye eşit değildir.

  • bir ilkel, türü ve değeri aynıysa, başka bir ilkel ile karşılaştırıldığında eşittir.


3
new String("foo") === new String("foo")is false:-P
Rocket Hazmat

10

newKelimesi burada bir suçlu ( her zamanki gibi diyorum olabilir) ...

Kullandığınızda new, nesneyle çalışma arzunuzu açıkça ifade edersiniz . Senin için şaşırtıcı olabilir ama bu:

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

... sana bir kudret verecek false. Çok basit: karşılaştırılan nesnelerin iç kısımları değil, nesnelerin referanslarıdır. Ve elbette, iki farklı nesne yaratıldığı için eşit değiller.

Muhtemelen kullanmak istediğiniz şey dönüşümdür :

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

... ve bu size, beklendiği truegibi, sonuç olarak verecektir , böylece foossonsuza dek eşitinizle sevinebilir ve zenginleşebilirsiniz . )


2
bunu kullanmayla ilgili hızlı bir soru. String'i (bir kurucu mu?) 'New' anahtar kelimesi olmadan çağırıyorsunuz. Bu, kapsamı String yapıcısı içinde atanan özelliklerle kirleteceğiniz anlamına gelmiyor mu? Yoksa kurucu yerel kod olduğu için bu olmaz mı? Başka bir deyişle, String işlevinin "this.a = 1;" içerdiğini varsayalım. - Bu senin fonksiyon / nesne artık tesiste = 1. gerekeceği anlamına geliyor
Michael Butler

Sanırım (ama kesin olarak söyleyemem) her bir 'kutucuk yapıcı' işlevi önce bağlamını kontrol eder - ve eğer 'yeni bir' değilse (yani bir prototip nesnesi), hemen dönüştürme yöntemine geçer. Örneğin String durumunda bu toString()yöntem olacaktır .
raina77ow


2

Node.js REPL'den (yüklüyse komut satırındaki "düğüm"):

> "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'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.