(NaN! = NaN) और (NaN! == NaN) में क्या अंतर है?


148

सबसे पहले मैं यह उल्लेख करना चाहता हूं कि मुझे पता है कि कैसे isNaN()और Number.isNaN()काम करते हैं। मैं पढ़ रहा हूँ निश्चित गाइड डेविड फ्लानागन से और वह करता है, तो मूल्य है, इसकी जांच करने के लिए एक उदाहरण देता है NaN:

x !== x

इस का परिणाम देगा trueयदि और केवल यदि xहै NaN

लेकिन अब मेरे पास एक सवाल है: वह सख्त तुलना का उपयोग क्यों करता है? क्योंकि ऐसा लगता है कि

x != x

उसी तरह व्यवहार करता है। यह दोनों संस्करणों का उपयोग करने, या मैं जावास्क्रिप्ट में कुछ मूल्य (रों) कि वापस आ जाएगी याद आ रही है सुरक्षित है trueके लिए x !== xऔर falseके लिए x != x?


10
यह हो सकता है कि फ़्लानगन !==चेक से अधिक !=चेक पसंद करता है। जहां तक ​​मैं जानता हूं कि कोई अन्य मूल्य नहीं है जहां x != x। लेकिन जावास्क्रिप्ट डेवलपर्स के दो अलग-अलग समूह हैं: जो लोग पसंद करते हैं !=और जो पसंद करते हैं !==, वे गति, स्पष्टता, स्पष्टता, आदि के लिए हो सकते हैं
स्टीव क्लोस्टर

30
जब सख्त तुलना उसी तरह व्यवहार करती है तो ढीली तुलना का उपयोग क्यों करें?
Ry-

3
@Raulucco: NaNएक अद्वितीय प्रकार नहीं है, यह एक संख्या है। यह एक अद्वितीय मूल्य है जो स्वयं के बराबर नहीं है।
टीजे क्राउडर

8
शीर्षक लोगों को गुमराह करने वाला लगता है। मैं इसे कुछ इस तरह बदलने का सुझाव दूंगा "क्या x = = x कभी x से अलग है! == x?"
टीजे क्राउडर

6
@femmestem: जियोर्गी ने कहा "इस मामले में" यह स्टाइल की बात है। और वह इसमें सही है। यह नहीं है शैली जब ऑपरेंड के प्रकार अलग-अलग हैं, लेकिन यह है जब वे एक ही कर रहे हैं शैली। अलग से: फलागन उन तुलनाओं को कर रहे हैं जो ===NaN के साथ बात करते हैं कि NaN खुद के बराबर नहीं है। वह "गलत नहीं है," वह एक शिक्षण अभ्यास के रूप में कर रहा है, यह दर्शाता है कि यह काम नहीं करता है।
टीजे क्राउडर

जवाबों:


128

सबसे पहले, मुझे बताना चाहिए कि NaNयह एक बहुत ही विशेष मूल्य है: परिभाषा के अनुसार, यह खुद के बराबर नहीं है। यह IEEE-754 मानक से आता है जो जावास्क्रिप्ट संख्या पर आकर्षित होता है। "एक नंबर नहीं" मूल्य कभी भी अपने आप के बराबर नहीं होता है, भले ही बिट्स एक सटीक मिलान हो। (जो कि वे IEEE-754 में जरूरी नहीं हैं, यह कई अलग-अलग "एक नंबर नहीं" मूल्यों के लिए अनुमति देता है।) यही कारण है कि यह भी आता है; जावास्क्रिप्ट में अन्य सभी मूल्य स्वयं के बराबर हैं, NaNबस विशेष है।

... क्या मुझे जावास्क्रिप्ट में कुछ मूल्य याद आ रहे हैं जो x =! x के लिए सही लौटेंगे और x = x के लिए गलत हैं?

नहीं आप नहीं हैं। के बीच एकमात्र अंतर है !==और !=यह है कि उत्तरार्द्ध प्रकार के बलपूर्वक करेगा यदि आवश्यक हो तो ऑपरेंड के प्रकार समान होने के लिए। में x != x, ऑपरेंड के प्रकार समान हैं, और इसलिए यह बिल्कुल वैसा ही है x !== x

यह सार समानता ऑपरेशन की परिभाषा की शुरुआत से स्पष्ट है :

  1. ReturnIfAbrupt (एक्स)।
  2. ReturnIfAbrupt (y)।
  3. यदि प्रकार (x) प्रकार (y) के समान है, तो

    सख्त समानता तुलना x === y प्रदर्शन करने का परिणाम लौटाएं।

  4. ...

पहले दो चरण बुनियादी पाइपलाइन हैं। तो वास्तव में, यह ==देखने के लिए पहला चरण है कि क्या प्रकार समान हैं और यदि हां, तो ===इसके बजाय करना है । !=और !==उस के केवल नकारात्मक संस्करण हैं।

तो अगर फलागन सही है कि केवल NaNसच के लिए दे x !== x, हम यह सुनिश्चित कर सकते हैं कि यह भी सच है कि केवल के NaNलिए सच होगा x != x

कई जावास्क्रिप्ट प्रोग्रामर का उपयोग करने के लिए डिफ़ॉल्ट है ===और !==टाइप ऑपरेटर्स ढीले ऑपरेटरों के साथ कुछ नुकसान से बचने के लिए है, लेकिन इस मामले में सख्त बनाम ढीले ऑपरेटर के फ्लैनगन के उपयोग में पढ़ने के लिए कुछ भी नहीं है।


मेरे पास फिर से 4.9.1 - Equality and Inequality Operatorsभाग है और यह उत्तर लगता है। के लिए प्रमुख मुद्दा ===तुलना है: If the two values have the same type, test them for strict equality as described above. If they are strictly equal, they are equal. If they are not strictly equal, they are not equal
जियोर्गी नेकुरी

@GiorgiNakeuri: मुझे यकीन नहीं है कि 4.9.1 आप किस बात का जिक्र कर रहे हैं, शायद फ्लैगन की किताब? लेकिन यह मूल रूप से कह रहा है कि ऊपर की कल्पना से बोली क्या कह रही है, हाँ।
टीजे क्राउडर

2
मैं इसे स्वीकार कर रहा हूं क्योंकि यह औपचारिक और सटीक फैशन में मेरे सवाल का जवाब देता है। स्पष्टीकरण के लिए धन्यवाद!
जियोर्गी नेकुरी

1
@ मोशे: "लाइव बाइंडिंग" से आपका क्या मतलब है? (अवधि कल्पना में प्रकट नहीं होता।) की तरह आप मतलब कुछ करो गोटो 0 के उदाहरण हैं जहां aवास्तव में एक समारोह है और एक ही मूल्य दो बार वापस नहीं करता है? मूल्य के रूप में वही बात नहीं है जिसके !==लिए यह सच होगा, जो कि ओपी के बारे में पूछा गया है। यह सिर्फ एक फ़ंक्शन है जो विभिन्न मूल्यों को लौटाता है। foo() !== foo()जरूरी नहीं कि या तो सच fooहो , क्योंकि प्रत्येक कॉल पर अलग-अलग मान वापस आ सकते हैं।
टीजे क्राउडर

1
@Moshe अच्छी तरह से गुण और getters के साथ गड़बड़ करने के लिए एक सुपर बुरा तरीका है। लेकिन यह बहुत हद तक GOTO 0 के उदाहरण के समान प्रतीत होता है, बस अप्रत्यक्ष की एक अतिरिक्त परत के साथ।
JAB

37

NaN के प्रयोजनों के लिए, !=और !==वही काम करें।

हालांकि, कई प्रोग्रामर जावास्क्रिप्ट में ==या उससे बचते हैं !=। उदाहरण के लिए, डगलस क्रॉकफोर्ड उन्हें जावास्क्रिप्ट भाषा के " बुरे भागों " के बीच मानते हैं क्योंकि वे अप्रत्याशित और भ्रामक व्यवहार करते हैं:

जावास्क्रिप्ट में समानता ऑपरेटरों के दो सेट हैं: ===और !==, और उनके दुष्ट जुड़वां ==और !=। अच्छे लोग उस तरह से काम करते हैं जिस तरह से आप उम्मीद करते हैं।

... मेरी सलाह है कि कभी भी दुष्ट जुड़वां बच्चों का उपयोग न करें। इसके बजाय, हमेशा उपयोग करें ===और !==


2
सवाल NaN (शीर्षक के बावजूद) के बारे में नहीं है। सवाल यह है कि "क्या मैं जावास्क्रिप्ट में कुछ मूल्य याद कर रहा हूं जो x =! X के लिए सही लौटेगा और x = x के लिए गलत होगा?"
टीजे क्राउडर

@TJCrowder दो सवाल, वास्तव में। पहला सवाल "क्या यह दोनों संस्करणों का उपयोग करना सुरक्षित है" और जवाब है कि दोनों संस्करण समान हैं। मुझे आपका "अंडर-द-हुड" उत्तर पसंद है जो सब कुछ विस्तार से बताता है।
jkdev

22

बस मज़े के लिए, मैं आपको एक कृत्रिम उदाहरण दिखाता हूँ जहाँ xनहीं है, NaNलेकिन ऑपरेटर वैसे भी अलग व्यवहार करते हैं। पहले परिभाषित करें:

Object.defineProperty(
  self,
  'x',
  { get: function() { return self.y = self.y ? 0 : '0'; } }
);

तो हमारे पास हैं

x != x // false

परंतु

x !== x // true

9
हा! :-) लेकिन यह प्रभावी रूप से है foo() != foo()जहाँ foo 1 तो 2 रिटर्न। उदाहरण के लिए, मान समान नहीं हैं, यह सिर्फ विभिन्न मूल्यों की तुलना कर रहा है।
टीजे क्राउडर

2

मैं केवल यह बताना चाहता हूं NaNकि x !== xवैश्विक वस्तु का उपयोग किए बिना पैदा होने वाली एकमात्र चीज नहीं है । इस व्यवहार को ट्रिगर करने के लिए बहुत सारे चतुर तरीके हैं। यहाँ एक गेटर्स का उपयोग कर रहा है:

var i = 0, obj = { get x() { return i++; }};
with(obj) // force dynamic context, this is evil. 
console.log(x === x); // false

जैसा कि अन्य उत्तर इंगित करते हैं, ==प्रकार का तालमेल करता है, लेकिन अन्य भाषाओं में और मानक के अनुसार - NaN एक संगणना विफलता को इंगित करता है, और अच्छे कारणों के लिए खुद के बराबर नहीं है।

मुझसे परे किसी कारण से लोगों ने जेएस के साथ इस समस्या का सामना किया है, लेकिन अधिकांश भाषाओं में युगल हैं (अर्थात्, सी, जावा, सी ++, सी #, पायथन और अन्य) इस सटीक व्यवहार को प्रदर्शित करते हैं और लोग इसके साथ ठीक हैं।


2
हाँ, यह वही है जो @TJCrowder ने GOTO_0 के उत्तर में टिप्पणी में उल्लेख किया है, है ना?
जियोर्गी नेकुरी

क्या आप स्पष्ट कर सकते हैं कि इन अन्य भाषाओं में अस्पष्ट प्रकार का ज़बरदस्ती कैसे प्राप्त करें?
काइकोवेनानियो

0

जैसा कि कभी-कभी, चित्र शब्दों से बेहतर होते हैं, इस तालिका की जांच करें (जो कि मेरे लिए एक टिप्पणी के बजाय इसका उत्तर देने का कारण है क्योंकि यह बेहतर दृश्यता प्राप्त करता है)।

वहाँ आप देख सकते हैं कि समानता की तुलना (===) केवल सही है यदि प्रकार और सामग्री मेल खाते हैं, तो

var f = "-1" === -1; //false

जबकि समानता समानता तुलना (==) केवल सामग्री की जाँच करती है * प्रकारों को परिवर्तित करके और फिर उनकी तुलना कड़ाई से:

var t = "-1" == -1; //true

हालांकि यह स्पष्ट नहीं है, ईसीएमए से परामर्श के बिना , जावास्क्रिप्ट की तुलना करते समय क्या विचार करता है, इस तरह से कि कोड बोले का मूल्यांकन सही होता है।

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