JavaScript'te, “0” neden false değerine eşittir, ancak 'if' ile test edildiğinde tek başına yanlış değildir?


232

Aşağıdaki "0"Javascript yanlış olduğunu gösterir :

>>> "0" == false
true

>>> false == "0"
true

Peki, aşağıdakiler neden yazdırılıyor "ha"?

>>> if ("0") console.log("ha")
ha

47
"0"bir dizedir ve boş olmadığından true olarak değerlendirilir.
Digital Plane

8
"0" === false [...] false

3
Javascript Angus Croll makale gerçeği göz atın. javascriptweblog.wordpress.com/2011/02/07/…
timrwood

8
'0'==falseancak '0' bir falsey değeri değildir (evet Javascript garip olabilir)
Linsey

5
@Linsey: Bütün "sahte" ve "gerçek" şey, değerlerin booleanlara nasıl dönüştürüldüğünü açıklamaktı. İki değeri ile karşılaştırdığınızda ==, hiçbir zaman boolelara dönüştürülmezler, bu yüzden geçerli değildir. (Dönüşüm için kurallar sayılara dönüştürmeyi tercih ediyor gibi görünüyor.)
0'da millimoose

Yanıtlar:


251

Bunun nedeni, açıkça yaptığınızda "0" == false, her iki tarafın da sayılara dönüştürülmesi ve ardından karşılaştırma yapılmasıdır.

Bunu yaptığınızda:, if ("0") console.log("ha")dize değeri test edilir. Boş olmayan herhangi truebir dize, boş bir dize false.

Eşittir (==)

İki işlenen aynı türde değilse , JavaScript işlenenleri dönüştürür ve ardından katı karşılaştırma uygular. İşlenenlerden biri sayı veya boole ise, işlenenler mümkünse sayılara dönüştürülür; aksi takdirde işlenenlerden biri dize ise, diğer işlenen mümkünse bir dizeye dönüştürülür. Her iki işlenen de nesne ise , JavaScript işlenenler bellekteki aynı nesneyi ifade ettiğinde eşit olan dahili başvuruları karşılaştırır.

( Mozilla Geliştirici Ağı'ndaki Karşılaştırma Operatörlerinden )


348

Sorunu gösteren tablolar:

doğruluk if ifadesi

ve == javascript'teki tüm nesne türlerinin doğru karşılaştırmaları

Hikayenin ahlaki kullanımı === akıl sağlığı gösteren katı eşitlik

tablo oluşturma kredisi: https://github.com/dorey/JavaScript-Equality-Table


2
Değerlerin başka bir sırası ile çok daha mantıklı gist.github.com/kirilloid/8165660
kirilloid

3
Bundan sonra, birisi asla katı karşılaştırma operatörleri kullanmadığını söylüyorsa, onunla bu masalarla yüzleşeceğim ve ağlamasını sağlayacağım. Yine de kavramını kavrayabildiğimden emin değilim NaN. Yani, typeof NaN // numberama NaN === NaN // false, hmm ...
Justus Romijn

4
Bir arkadaşım f.cl.ly/items/3b0q1n0o1m142P1P340P/javascript_equality.html - yukarıdaki ile aynı grafikleri yaptı, ancak biraz daha kolay okundu.
Lucy Bain

@JustusRomijn temsil etmek için birden fazla değer vardır NaN, bu yüzden 2 NaN karşılaştırırken, bunlar farklı değerlerdir (sanırım). İlk teklifi buradan okuyun .
cychoi

4
Bu tabloların bir hatası var. Ne ==de ===operatör için [], {}, [[]], [0]ve [1]değerler true değerlendirmek gerekmez. Demek istediğim [] == []ve [] === []yanlış da.
Herbertusz

38

Spesifikasyonlara göre.

12.5 if ifadesi 
.....

2. ToBoolean (GetValue (exprRef)) doğruysa, 
a. İlk İfadeyi değerlendirmenin sonucunu döndür.
3. Başka, 
....

ToBoolean, spesifikasyona göre,

ToBoolean soyut işlemi, argümanını Tablo 11'e göre Boolean türünde bir değere dönüştürür:

Ve bu tablo dizeler hakkında bunu söylüyor:

resim açıklamasını buraya girin

Bağımsız değişken boş Dize ise (uzunluğu sıfırdır) sonuç false olur; aksi takdirde sonuç doğrudur

Şimdi, "0" == falsedeğerini soyut işlemden aldığını belirten eşitlik operatörünü neden GetValue(lref)sağ taraf için aynı eşleştiğini açıklamanız gerektiğini açıklamak için.

Bu ilgili kısmı şöyle açıklar:

IsPropertyReference (V) ise, 
a. HasPrimitiveBase (V) yanlışsa, [[Get]] dahili baz yöntemi olsun, aksi halde olsun
aşağıda tanımlanan özel [[Get]] dahili yöntem olabilir. 
b. Bu değer olarak base kullanarak get internal yöntemini çağırmanın sonucunu döndürün
Bağımsız değişken için GetReferencedName (V)

Başka bir deyişle, bir dize, dahili get yöntemini geri çağıran ve yanlış görünecek olan ilkel bir tabana sahiptir.

GetValue işlem kullanımını kullanarak bir şeyleri değerlendirmek ==istiyorsanız, kullanarak değerlendirmek istiyorsanız ToBoolean, kullanın ===("katı" eşitlik operatörü olarak da bilinir)


"a string has a primitive base, which calls back the internal get method and ends up looking false"Bu tüm dizeler için geçerli mi?
aziz punjani

@Interstellar_Coder Section 8.12.3: [[Get]] (P)nasıl çalıştığını açıklar. Bu dize 0 olduğu durumlar için doğrudur, çünkü diğer dahili çağrıların bir demetini yapar, bu da sonuçta GetOwnProperty"ne olursa olsun" ın bir veri özelliği olduğunu görür ve daha sonra bu değere geri döner. Bu yüzden "0" yanlıştır ve "blah" doğrudur. Douglas Crockford'un Yahoo geliştirici tiyatrosundaki videolarına göz atın, JavaScript'teki "doğruluk" u benden biraz daha az karmaşık olarak tanımlıyor. "Doğruluk" ve "sahteciliğin" ne anlama geldiğini anlarsanız, Bobince'nin cevabını hemen anlayacaksınız.
Gizli

1
Spesifikasyonu nerede bulabilirim?
user985366

12

Dize nerede PHP bulunuyor "0"falsy olduğu (yanlış-zaman-used-in-boolean-bağlam). JavaScript'te, boş olmayan tüm dizeler doğrudur.

İşin püf noktası, ==bir boole karşı boolean bağlamında değerlendirme yapmıyorsa, sayıya dönüşür ve ondalık olarak ayrıştırılarak yapılan dizelerde. Yani 0doğruluk boole yerine Sayı alırsınız true.

Bu çok zayıf bir dil tasarımı ve talihsiz ==operatörü kullanmamaya çalışmamızın nedenlerinden biri . ===Bunun yerine kullanın .


7
// I usually do this:

x = "0" ;

if (!!+x) console.log('I am true');
else      console.log('I am false');

// Essentially converting string to integer and then boolean.

4

Etrafınızdaki alıntılarınız 0, doğru olarak değerlendirilen bir dize yapar.

Tırnak işaretleri kaldırın ve işe yarayacaktır.

if (0) console.log("ha") 

doğru, "nasıl işe yarayacağı" ile ilgili değil ama soru daha çok "neden bu şekilde davrandı?"
nonopolarite


1

"İf" ifadesi doğruluk için test ederken, tip-eşit denklik için çift-eşit testler. Bir ip her zaman doğrudur, burada diğerlerinin de belirttiği gibi. Çifte eşitlik her iki işlenenini de doğruluk açısından test ediyor ve sonuçları karşılaştırıyor olsaydı, sezgisel olarak varsaydığınız sonucu elde edersiniz, yani ("0" == true) === true. Doug Crockford'un mükemmel JavaScript'i: İyi Parçalar'da dediği gibi , "[== işlenen türlerini zorlayan kurallar] karmaşık ve unutulmaz .... Geçişsizlik eksikliği endişe vericidir." İşlenenlerden birinin diğerine uyacak şekilde tipte zorlandığını ve "0" ın sayısal sıfır olarak yorumlandığını söylemek yeterlidir,


1

== Eşitlik operatörü, bağımsız değişkenleri sayılara dönüştürdükten sonra değerlendirir. Dize sıfır "0" Sayı veri türü ve false dönüştürülür Yani Numara 0. dönüştürülür So

"0" == false // true

Aynısı `

false == "0" //true

=== Sıkı eşitlik denetimi, bağımsız değişkenleri orijinal veri türüyle değerlendirir

"0" === false // false, because "0" is a string and false is boolean

Aynısı aşağıdakiler için de geçerlidir

false === "0" // false

İçinde

if("0") console.log("ha");

"0" dizesi hiçbir bağımsız değişkenle karşılaştırılamaz ve dize, hiçbir bağımsız değişkenle karşılaştırılıncaya kadar gerçek bir değerdir. Aynen öyle

if(true) console.log("ha");

Fakat

if (0) console.log("ha"); // empty console line, because 0 is false

'


1

Bunun nedeni, JavaScript'in Boole bağlamlarında ve kodunuzda tür zorlaması kullanmasıdır

if ("0") 

boole bağlamında true değerine zorlanacaktır.

Javascript'te, boole bağlamlarında true değerine zorlanacak ve böylece if bloğunu yürütecek başka doğruluk değerleri vardır:

if (true)
if ({})
if ([])
if (42)
if ("0")
if ("false")
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)

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.