जेएसएन में एनएनएन (शून्य) == गलत क्यों है?


129

जेएस में यह कोड मुझे एक पॉपअप कहता है "मुझे लगता है कि अशक्त एक संख्या है", जो मुझे थोड़ा परेशान करता है। मैं क्या खो रहा हूँ?

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

मैं फ़ायरफ़ॉक्स 3 का उपयोग कर रहा हूँ। क्या यह ब्राउज़र बग है?

अन्य परीक्षण:

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

तो, समस्या NaN के साथ एक सटीक तुलना नहीं लगती है?

संपादित करें: अब सवाल का जवाब दिया गया है, मैंने संग्रह के लिए एक बेहतर संस्करण के लिए अपनी पोस्ट को साफ कर दिया है। हालाँकि, यह कुछ टिप्पणियों को प्रस्तुत करता है और कुछ जवाबों को थोड़ा असंगत बनाता है। उनके लेखकों को दोष मत दो। जिन चीज़ों में मैंने बदलाव किया, वे थीं:

  • एक नोट निकालते हुए कहा कि मैंने पहली बार में हेडलाइन को खराब कर दिया था, इसके अर्थ को बदलकर
  • पहले के जवाबों से पता चला कि मैं स्पष्ट रूप से पर्याप्त नहीं था कि मुझे ऐसा क्यों लगा कि व्यवहार अजीब था, इसलिए मैंने उन उदाहरणों को जोड़ा जो एक स्ट्रिंग की जांच करते हैं और एक मैनुअल तुलना करते हैं।

3
क्या आपका मतलब यह नहीं है कि "isNaN (null) == गलत" क्यों है?
मैट रोजिश

आपके कोड के आधार पर, isnan (null) गलत लौट रहा है (null "not a number") यदि यह कहता है कि "मुझे लगता है कि null एक संख्या है"।
devinmoore

जवाबों:


114

मेरा मानना ​​है कि कोड पूछने की कोशिश कर रहा है, " xसंख्यात्मक है?" यहाँ के विशिष्ट मामले के साथ x = nullisNaN()इस प्रश्न का उत्तर देने के लिए फ़ंक्शन का उपयोग किया जा सकता है, लेकिन शब्दार्थ यह विशेष रूप से मूल्य का उल्लेख कर रहा है NaN। विकिपीडिया से इसके लिए NaN:

NaN ( एन ओटी एन umber) संख्यात्मक डेटा प्रकार का एक मान है जो विशेष रूप से फ्लोटिंग-पॉइंट गणनाओं में अपरिभाषित या अप्राप्य मूल्य का प्रतिनिधित्व करता है।

ज्यादातर मामलों में हमें लगता है कि "शून्य संख्यात्मक है?" नहीं होना चाहिए। हालाँकि, isNaN(null) == falseशब्दार्थ सही है, क्योंकि nullऐसा नहीं है NaN

यहाँ एल्गोरिथम विवरण दिया गया है:

फ़ंक्शन पास isNaN(x)किए गए पैरामीटर को नंबर 1 (समकक्ष Number(x)) के रूप में परिवर्तित करने का प्रयास करता है और फिर मान होने पर परीक्षण करता है NaN। यदि पैरामीटर को एक संख्या में नहीं बदला जा सकता है, Number(x)तो NaN2 वापस आ जाएगा । इसलिए, यदि xकिसी संख्या में पैरामीटर का रूपांतरण परिणाम में आता है NaN, तो यह सच है; अन्यथा, यह गलत है।

इसलिए विशिष्ट स्थिति में x = null, nullसंख्या 0 में परिवर्तित हो जाती है, (मूल्यांकन करने की कोशिश करें Number(null)और देखें कि यह 0 देता है,) और isNaN(0)गलत रिटर्न करता है। एक स्ट्रिंग जो केवल अंकों की होती है, उसे एक संख्या में बदला जा सकता है और isNaN भी गलत हो जाता है। एक स्ट्रिंग (जैसे 'abcd') जिसे किसी संख्या में परिवर्तित नहीं किया जा सकता isNaN('abcd')है, वह विशेष रूप से Number('abcd')रिटर्न के कारण सही लौटाएगा NaN

इन स्पष्ट मामलों के अलावा, NaN 0/0 की वापसी के लिए मानक संख्यात्मक कारण हैं।

प्रश्न में दिखाए गए समानता के लिए प्रतीत होता है असंगत परीक्षणों के लिए, का व्यवहार NaNइस तरह निर्दिष्ट किया गया है कि कोई भी तुलना x == NaNझूठी है, भले ही अन्य ऑपरेंड की परवाह किए बिना, जिसमें 1 भी शामिल NaNहै ।


8
BTW NaN !== NaN,। इसलिए, मुझे लगता है, यह कहना पूरी तरह से सही नहीं है Number('abcd') == NaNक्योंकि Number('abcd')यह NaNनहीं के बराबर है NaN। मैं जावास्क्रिप्ट स्वीकार करते हैं।
nilfalse

हाँ। मेरा आशय यह Number('abcd')है कि NaNलेकिन मैं यह मानता हूं कि यह समानता के लिए सही है, जो कि नहीं है। मैं इसे संपादित करूंगा।
ग्लेन मॉस

मुझे आश्चर्य है कि क्यों isNaNऔर Numberइस तरह से व्यवहार करने के लिए डिज़ाइन किए गए हैं?
टाइमिडबॉय

1
के रूपांतरण nullके लिए 0केवल (इस प्रसंग में कम से कम) के भीतर होती है isNaN()समारोह है, जो अपने तर्क coerces।
ग्लेन मॉस

3
संख्या (शून्य) == 0 लेकिन parseInt (नल) == NaN जेएस से प्यार
जोशबर्क

31

मैं बस इस मुद्दे पर अपने आप में भाग गया।

मेरे लिए, NNN का उपयोग करने का सबसे अच्छा तरीका ऐसा है

isNaN(parseInt(myInt))

ऊपर से फ़िज़ोम का उदाहरण लेते हुए,

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]

(मैंने इनपुट के अनुसार परिणाम को संशोधित किया, आशा है कि यह पढ़ने में आसान बनाता है।)

यह मुझे बेहतर लगता है।


1
काम नहीं करेगा अगर myInt= "123d"। parseInt"123d" को 123 में परिवर्तित करता है, जो तब isNaNपरीक्षण में विफल रहता है ।
दिवेश प्रीमियर

वास्तव में, यदि आप उस परिदृश्य को भी पकड़ना चाहते हैं, तो मैं अपने उत्तर और ग्लेन के संयोजन का सुझाव देता हूं। जो इस तरह दिखेगा isNaN(parseInt(str,10)) || isNaN(Number())। btw - मेरे लिए, चूंकि मुझे parseIntस्ट्रिंग के संख्यात्मक मान का उपयोग करने के लिए चलना है, जिससे "123d" को वैध संख्या के रूप में माना जा सकता है। हालाँकि मुझे उस परिदृश्य का भी पता लगाने की आवश्यकता है।
लड़का मोगरबी

8

(मेरी अन्य टिप्पणी एक व्यावहारिक दृष्टिकोण लेती है। यहाँ सैद्धांतिक पक्ष है।)

मैंने ECMA 262 मानक को देखा, जो कि जावास्क्रिप्ट को लागू करता है। उनका विनिर्देशन:

ToNumber को उसके तर्क पर लागू करता है, फिर यदि परिणाम NaN है, तो सही है और अन्यथा गलत देता है।

खंड 9.3 के व्यवहार को निर्दिष्ट करता है ToNumber(जो एक कॉल करने योग्य कार्य नहीं है, बल्कि टाइप रूपांतरण प्रणाली का एक घटक है)। तालिका को सारांशित करने के लिए, कुछ इनपुट प्रकार एक NaN का उत्पादन कर सकते हैं। ये प्रकार हैं undefined, टाइप number(लेकिन केवल मान NaN), कोई भी वस्तु जिसका आदिम प्रतिनिधित्व है NaN, और जो भी stringपार्स नहीं किया जा सकता है। इस पत्ते undefined, NaN, new Number(NaN), और सबसे तार।

कोई भी ऐसा इनपुट जो NaNउत्तीर्ण होने पर आउटपुट के रूप में ToNumberउत्पन्न होता है trueजब उसे खिलाया जाता है isNaN। चूंकि nullसफलतापूर्वक एक संख्या में परिवर्तित किया जा सकता है, यह उत्पादन नहीं करता है true

और इसलिए ही।


7

यह वास्तव में परेशान करने वाला है। यहां उन मानों की एक सरणी है, जिनका मैंने परीक्षण किया था:

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

यह (फायरबग कंसोल में) का मूल्यांकन करता है:

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

जब मैं कॉल करता हूं x.map(isNaN)(प्रत्येक मूल्य पर NNN को कॉल करने के लिए), मुझे मिलता है:

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

निष्कर्ष में, isNaNबहुत बेकार लग रहा है! ( संपादित करें : इसे छोड़कर यह पता चलता है कि NNN केवल संख्या से अधिक परिभाषित है , इस मामले में यह ठीक काम करता है - सिर्फ एक भ्रामक नाम के साथ।)

संयोग से, यहाँ उन मूल्यों के प्रकार हैं:

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

आप क्या सोचते हैं कि NaN का मतलब क्या होना चाहिए? आपको क्या लगता है कि NaN के बारे में इतना भ्रामक या इसके लिए परीक्षण किया जा रहा है? आप क्यों परेशान हैं?
बेकिम बकाज

खैर, यह 8 साल पहले था, लेकिन ऐसा लगता है कि मैं परेशान था कि 1) यह उन मानों के लिए असंगत परिणाम है जो टाइप नंबर के नहीं हैं, और 2) यह कभी भी उस चीज के लिए सही है जो टाइप नंबर की नहीं है। क्योंकि एक स्ट्रिंग नहीं है, वास्तव में, एक एन.एन. (मेरा दूसरा उत्तर भी देखें, जो बताता है कि ऐसा क्यों होता है।)
अपने मॉड का अच्छी तरह से इलाज करें

5

नल NaN नहीं है, साथ ही एक स्ट्रिंग NaN नहीं है। isNaN () बस परीक्षण अगर आप वास्तव में NaN वस्तु है।


लेकिन तब कम से कम एक स्ट्रिंग एक NaN ऑब्जेक्ट में डाली जाती है, जैसा कि isNaN ("टेक्स्ट") सही है।
हेन्नो फिएट

1

जब जेएस की बात आती है तो मुझे बिल्कुल यकीन नहीं है, लेकिन मैंने अन्य भाषाओं में भी इसी तरह की चीजें देखी हैं और यह आमतौर पर होता है क्योंकि फ़ंक्शन केवल यह जांच रहा है कि क्या नल NaN के बराबर है (यानी null === NaN गलत होगा)। दूसरे शब्दों में, ऐसा नहीं है कि यह सोचता है कि अशक्तता वास्तव में एक संख्या है, बल्कि यह है कि अशक्त NaN नहीं है। यह संभवतः इसलिए है क्योंकि दोनों को JS में अलग-अलग रूप से दर्शाया गया है ताकि वे बिल्कुल समान न हों, उसी तरह से 9! == '9'।


1

ES5 में, इसे isNaN (number)सही के रूप में परिभाषित किया जाता है यदि तर्क NaN के साथ सामंजस्य स्थापित करता है, और अन्यथा झूठा लौटता है।

  • यदि ToNumber (संख्या) NaN है, तो सही लौटें।
  • नहीं तो झूठा लौट आता है।

और सार ऑपरेशन ToNumber रूपांतरण तालिका देखें । तो यह आंतरिक रूप से जेएस इंजन का मूल्यांकन ToNumber(Null)है +0, फिर अंततः isNaN(null)हैfalse


0

ध्यान दें:

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

== ऑपरेटर टाइप-रूपांतरण करता है, जबकि === नहीं करता है।

डगलस क्रॉकफोर्ड की वेबसाइट , एक याहू! जावास्क्रिप्ट इंजीलवादी, इस तरह से सामान के लिए एक महान संसाधन है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.