JS'de neden isNaN (null) == false?


130

JS'deki bu kod bana biraz rahatsız edici bulduğum "boş bir sayı olduğunu düşünüyorum" diyen bir açılır pencere veriyor. Neyi kaçırıyorum?

if (isNaN(null)) {
  alert("null is not a number");
} else {
  alert("i think null is a number");
}

Firefox 3 kullanıyorum. Bu bir tarayıcı hatası mı?

Diğer testler:

console.log(null == NaN);   // false
console.log(isNaN("text")); // true
console.log(NaN == "text"); // false

Öyleyse, sorun NaN ile tam bir karşılaştırma gibi görünmüyor?

Düzenleme: Şimdi soru cevaplandı, arşivin daha iyi bir sürümüne sahip olmak için gönderimi temizledim. Ancak bu, bazı yorumları ve hatta bazı cevapları biraz anlaşılmaz hale getiriyor. Yazarlarını suçlamayın. Değiştirdiğim şeyler arasında şunlar vardı:

  • İlk başta anlamını tersine çevirerek manşeti alt üst ettiğimi söyleyen bir not kaldırıldı
  • Önceki cevaplar, davranışın neden tuhaf olduğunu düşündüğümü yeterince açık bir şekilde belirtmediğimi gösterdi, bu yüzden bir dizeyi kontrol eden ve manuel bir karşılaştırma yapan örnekleri ekledim.

3
"Neden isNaN (null) == false" demek istemiyorsunuz?
Matt Rogish

Kodunuza bağlı olarak, isnan (null), "Bence boş bir sayıdır" diyorsa yanlış (null "sayı değil") döndürüyor.
devinmoore

Yanıtlar:


114

Kodun sormaya çalıştığına inanıyorum, " xsayısal mı?" buradaki özel durum ile x = null. İşlev isNaN(), bu soruyu yanıtlamak için kullanılabilir, ancak anlamsal olarak özellikle değere atıfta bulunur NaN. Wikipedia'dan NaN:

NaN ( N ot a N umber), özellikle kayan nokta hesaplamalarında tanımlanmamış veya temsil edilemeyen bir değeri temsil eden sayısal veri türünün bir değeridir.

Çoğu durumda "boş sayısal mı?" hayır olmalı. Ancak, isNaN(null) == falseanlamsal olarak doğrudur, çünkü nulldeğildir NaN.

Algoritmik açıklama şu şekildedir:

İşlev isNaN(x), aktarılan parametreyi 1 sayısına (eşdeğerine Number(x)) dönüştürmeye çalışır ve ardından değerin olup olmadığını test eder NaN. Parametre bir sayıya dönüştürülemezse, 2Number(x) döndürür . Bu nedenle, parametrenin bir sayıya dönüştürülmesiyle sonuçlanırsa , true; aksi takdirde yanlış döndürür.NaNxNaN

Bu nedenle, belirli durumda x = null, null0 sayısına dönüştürülür (değerlendirmeyi deneyin Number(null)ve 0 döndürdüğünü görün) ve isNaN(0)false döndürür. Yalnızca rakamlardan oluşan bir dize bir sayıya dönüştürülebilir ve isNaN ayrıca yanlış döndürür. Bir 'abcd'sayıya dönüştürülemeyen bir dize (örneğin ) isNaN('abcd'), özellikle Number('abcd')döndürdüğü için true döndürülmesine neden olur NaN.

Bu açık uç durumlara ek olarak, 0/0 gibi NaN döndürmenin standart sayısal nedenleridir.

Soruda gösterilen eşitlik için görünüşte tutarsız testlere gelince, davranışı, kendisi de dahil olmak üzere diğer işlenen ne olursa olsun NaNherhangi bir karşılaştırma x == NaNyanlış olacak şekilde belirtilir 1 .NaN


8
BTW NaN !== NaN,. Bu yüzden, Number('abcd') == NaNçünkü eşit değil Number('abcd'), çünkü demek tamamen doğru NaNdeğil NaN. JavaScript'e bayılıyorum.
nilfalse

Evet. Bunu ifade etmek içindir Number('abcd')olduğunu NaNama bunun böyle değildir ki, eşitlik için doğrudur testler olduğunu ima etti. Düzenleyeceğim.
Glenn Moss

Merak ediyorum neden böyle davranmak için tasarlandı isNaNve Numbertasarlandı?
timidboy

1
Dönüştürülmesi nulliçin 0sadece bu bağlamda (en az) içinde gerçekleşir isNaN(), bağımsız değişkeni coerces fonksiyonu.
Glenn Moss

3
Number (null) == 0 ama parseInt (null) == NaN love JS
JoshBerke

31

Bu sorunla kendim karşılaştım.

Benim için isNaN'ı kullanmanın en iyi yolu böyle

isNaN(parseInt(myInt))

phyzome örneğini yukarıdan alarak,

var x = [undefined, NaN,     'blah', 0/0,  null, 0,     '0',   1,     1/0, -1/0,  Number(5)]
x.map( function(n){ return isNaN(parseInt(n))})
        [true,      true,    true,   true, true, false, false, false, true, true, false]

(Sonucu girdiye göre hizaladım, umarım okumayı kolaylaştırır.)

Bu bana daha iyi geliyor.


1
myIntİf = "123d" çalışmaz . parseInt"123d" yi 123'e dönüştürür ve ardından isNaNtesti geçemez .
divesh premdeep

gerçekten, bu senaryoyu da yakalamak istiyorsanız, cevabımla Glenn'inkini birleştirmenizi öneririm. bunun gibi görünecek isNaN(parseInt(str,10)) || isNaN(Number()). btw - benim için, parseIntdizenin sayısal değerini kullanmak için çalıştırmam gerektiğinden, "123d" nin geçerli sayı olarak kabul edilmesine izin vermek yeterli. Ancak bu senaryoyu da tespit etmem gerektiğini görüyorum.
guy mograbi

8

(Diğer yorumum pratik bir yaklaşım benimsiyor. İşte teorik taraf.)

Javascript'in uyguladığı ECMA 262 standardına baktım . İsNan için özellikleri:

ToNumber öğesini bağımsız değişkenine uygular, ardından sonuç NaN ise true, aksi takdirde false döndürür.

Bölüm 9.3, ToNumber(çağrılabilir bir işlev değil, daha çok tür dönüştürme sisteminin bir bileşeni olan) davranışını belirtir . Tabloyu özetlemek gerekirse, belirli giriş türleri bir NaN üretebilir. Bunlar tür undefined, tür number(ancak yalnızca değer NaN), ilkel gösterimi olan herhangi bir nesne NaNve stringayrıştırılamayan nesnelerdir . Bu yapraklar undefined, NaN, new Number(NaN)ve en dizeleri.

Gönderildiğinde NaNçıktı olarak üreten böyle bir girdi, beslendiğinde ToNumberbir üretecektir . Yana kutu başarıyla sayıya dönüştürülecek, bu üretmez .trueisNaNnulltrue

Ve bu nedenle.


7

Bu gerçekten rahatsız edici. İşte test ettiğim değerler dizisi:

var x = [undefined, NaN, 'blah', 0/0, null, 0, '0', 1, 1/0, -1/0, Number(5)]

(Firebug konsolunda) şunları değerlendirir:

,NaN,blah,NaN,,0,0,1,Infinity,-Infinity,5

Aradığımda x.map(isNaN)(her değerde isNaN'ı çağırmak için), şunu elde ederim:

true,true,true,true,false,false,false,false,false,false,false

Sonuç olarak, isNaNoldukça faydasız görünüyor! ( Düzenleme : Bunun dışında isNaN yalnızca Number üzerinden tanımlanır , bu durumda gayet iyi çalışır - sadece yanıltıcı bir adla.)

Bu arada, işte bu değerlerin türleri:

x.map(function(n){return typeof n})
-> undefined,number,string,number,object,number,string,number,number,number,number

NaN'nin ne anlama geldiğini düşünüyorsunuz? NaN hakkında veya onu test ederken bu kadar yanıltıcı olan nedir? Neden rahatsızsın
Bekim Bacaj

Bu 8 yıl önceydi, ama 1) Number türünde olmayan değerler için tutarsız sonuçlara sahip olması ve 2) Number türünde olmayan bir şey için true döndürmesi beni rahatsız ediyor gibi görünüyor. Çünkü bir dizge aslında bir NaN değildir. (Bunun neden olduğunu açıklayan diğer cevabıma da bakın.)
modlarınıza iyi davranın

5

Null, NaN değildir ve bir dize NaN değildir. isNaN () sadece gerçekten NaN nesnesine sahip olup olmadığınızı test edin.


Ancak isNaN ("text") true döndürdüğü için en azından bir dizge bir NaN nesnesine dönüştürülür.
Hanno Fietz

1

JS'ye geldiğinde tam olarak emin değilim ama diğer dillerde de benzer şeyler gördüm ve bunun nedeni genellikle işlevin yalnızca null değerinin NaN'ye tam olarak eşit olup olmadığını kontrol ediyor olması (yani null === NaN yanlış olacaktır). Başka bir deyişle, null'un aslında bir sayı olduğunu düşünmesi değil, null'un NaN olmamasıdır. Bunun nedeni muhtemelen her ikisinin de JS'de farklı şekilde temsil edilmesidir, böylece 9! == '9' ile aynı şekilde tam olarak eşit olmayacaklardır.



0

Not:

"1" == 1 // true
"1" === 1 // false

== operatörü tür dönüştürme yapar, === ise yapmaz.

Douglas Crockford'un web sitesi , bir Yahoo! JavaScript evangelisti, bunun gibi şeyler için harika bir kaynaktır.

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.