क्यों `null> = 0 && null <= 0` लेकिन नहीं` null == 0`?


142

मुझे एक रूटीन लिखना था जो किसी चर के मान को 1 से बढ़ाता है यदि उसका प्रकार है numberऔर चर को 0 असाइन करता है यदि नहीं, तो चर शुरू में nullया undefined

पहला कार्यान्वयन v >= 0 ? v += 1 : v = 0इसलिए हुआ क्योंकि मुझे लगा कि कोई भी संख्या एक अंकगणितीय अभिव्यक्ति को गलत नहीं बनाएगी, लेकिन यह गलत है क्योंकि null >= 0इसका मूल्यांकन सही है। तब मैंने सीखा कि nullव्यवहार 0 जैसा है और निम्नलिखित अभिव्यक्तियों का मूल्यांकन सभी सच है।

  • null >= 0 && null <= 0
  • !(null < 0 || null > 0)
  • null + 1 === 1
  • 1 / null === Infinity
  • Math.pow(42, null) === 1

बेशक, nullनहीं है 0 null == 0का मूल्यांकन असत्य के लिए किया गया है। यह प्रतीत होता है tautological अभिव्यक्ति (v >= 0 && v <= 0) === (v == 0)झूठी है।

null0 जैसा क्यों है , हालांकि यह वास्तव में 0 नहीं है?


3
वह जावास्क्रिप्ट के बारे में बात कर रहा है। आपका उदाहरण PHP में है। PHP ऑपरेटर में == एक विशेष तरीके से मूल्यों की तुलना करता है। आप "10" == "1e1" (जो सच है) जैसे कुछ वास्तव में पागल तुलना कर सकते हैं। यदि आप ऑपरेटर === का उपयोग करते हैं, तो आपको एक अलग परिणाम प्राप्त होगा क्योंकि यह जांचता है कि क्या प्रकार के साथ ही साथ मान भी मेल खाता है। इस लिंक को देखें: php.net/manual/en/language.operators.comparison.php
पीजूसन

PHP '==' ऑपरेटर वास्तव में "विशेष" तरीके से काम करता है।
दो-बिट अल्केमिस्ट

आपकी आवश्यकता 0 के बजाय 1 पर गिनती शुरू करने के लिए था तो इस बात है कि या तो शुरू कर रहे हैं वेतन वृद्धि काउंटर करने के लिए एक बहुत संक्षिप्त तरीका है nullया undefined:c = -~c // Results in 1 for null/undefined; increments if already a number
आटेस गोरल

1
undefinedएक वैरिएबल वैल्यू है, वैरिएबल के लिए जिसे इनिशियलाइज़ नहीं किया गया है। nullदूसरी ओर, एक खाली वस्तु मूल्य है, और संख्याओं के साथ मिश्रित नहीं होना चाहिए। nullसंख्याओं के साथ संयुक्त नहीं होना चाहिए, इसलिए अशक्त को संख्याओं की तरह व्यवहार नहीं करना चाहिए।
मत्ती

1
@AtesGoral - श्लोक, लेकिन गैर-स्पष्ट। लोगों को याद दिलाते हुए कि जब भी कुछ गैर-स्पष्ट किया जाता है, तो कृपया यह बताते हुए एक टिप्पणी जोड़ें कि कोड क्या करता है। ज्यादातर स्थितियों में, मैं इसे "समय से पहले अनुकूलन" पर विचार करूंगा, यह देखते हुए कि यह एक लघु प्रदर्शन लाभ के लिए स्पष्टता का कारोबार करता है।
टूलमेकरसेव

जवाबों:


207

आपका असली सवाल लगता है:

क्यों:

null >= 0; // true

परंतु:

null == 0; // false

वास्तव में क्या होता है कि ग्रेटर-थ्रू-या-बराबर ऑपरेटर ( >=), ToPrimitiveएक प्रकार के संकेत के साथ, प्रकार की जबरदस्ती ( ) करता है Number, वास्तव में सभी संबंधित ऑपरेटरों का यह व्यवहार है।

nullसमान ऑपरेटर ( ==) द्वारा एक विशेष तरीके से व्यवहार किया जाता है । एक संक्षिप्त में, यह केवल coerces लिए undefined:

null == null; // true
null == undefined; // true

मूल्य जैसे false, '', '0', और []संख्यात्मक प्रकार बलात्कार के अधीन है, उन सभी को शून्य करने के लिए मजबूर कर रहे हैं।

आप इस प्रक्रिया का आंतरिक विवरण The Abstract Equality Comparison Algorithm और The Abstract Relational Comparison Algorithm में देख सकते हैं

संक्षेप में:

  • संबंधपरक तुलना: यदि दोनों मान स्ट्रिंग प्रकार नहीं हैं, तो दोनों ToNumberपर कहा जाता है। यह +सामने वाले को जोड़ने के समान है , जो अशक्त करने के लिए मजबूर करता है 0

  • समानता तुलना: केवल ToNumberस्ट्रिंग्स, नंबर और बुलियन पर कॉल करता है।


1
हाय सीएमएस, आपके स्पष्टीकरण के अनुसार, शून्य आदिम 0 है, इसलिए 0> = 0 सही है और == झूठा वापस आ रहा है। लेकिन एक्वा एल्गोरिथम के अनुसार यदि टाइप (x) ऑब्जेक्ट है और टाइप (y) या तो स्ट्रिंग या संख्या है, तुलना ToPrimitive का परिणाम लौट (x) == इस में y.then यह true.please मुझे समझाने लौटना चाहिए
भरत muppa

मेरे लिए जवाब एक उत्तर प्रदान नहीं करता है - null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined:- और क्या? क्या आप समझा सकते हैं, क्यों null >= 0? :)
एंड्री डाइनको

@bharathmuppa @ andrey-deineko: शेष CMS का उत्तर यहां दिया गया है: The Abstract Relational Comparison Algorithm जो बिंदु 3 में बताता है। यदि दोनों मान टाइपिंग नहीं हैं, तो ToNumber को दोनों पर बुलाया जाता है। यह +सामने वाले को जोड़ने के समान है , जो अशक्त करने के लिए मजबूर करता है 0। समानता केवल स्ट्रिंग्स, नंबरों और बुलियन पर टूनंबर को बुलाती है।
माइकल लिकोरी

7
अच्छा वर्णन है, लेकिन मुझे यह पसंद नहीं है। किसी भी भाषा में (x == 0 || x> 0) के बराबर होना चाहिए (x> = 0)। जावास्क्रिप्ट एक बेवकूफ भाषा है।
जॉन हेन्केल

1
यह वास्तव में वास्तव में एक बग है (क्योंकि गणितीय रूप से यह गलत है) और इसके बारे में कुछ भी नहीं है क्योंकि लाखों वेबसाइट अशक्त तुलना पर निर्भर करती हैं ^ ^ '
mahieddine

14

मैं समस्या की दृश्यता को और बेहतर बनाने के लिए प्रश्न का विस्तार करना चाहता हूं:

null >= 0; //true
null <= 0; //true
null == 0; //false
null > 0;  //false
null < 0;  //false

इसमें बिलकुल मतलब नहीं है। मानव भाषाओं की तरह, इन चीजों को दिल से सीखने की जरूरत है।


1
जैसा कि ऊपर वर्णित है, इसे सिर्फ एक अपवाद के साथ समझाया जा सकता है कि कैसे == अशक्त व्यवहार करता है, अन्यथा सभी मामलों में शून्य को संख्या (शून्य) का उपयोग करके 0 में परिवर्तित किया जा रहा है
सौरभ रांका

5

जावास्क्रिप्ट में सख्त और टाइप-कंवर्टिंग दोनों प्रकार के हैं

null >= 0;सच है लेकिन (null==0)||(null>0)झूठ है

null <= 0;सच है लेकिन (null==0)||(null<0)झूठ है

"" >= 0 यह भी सच है

संबंधपरक अमूर्त तुलनाओं के लिए (<=,> =), ऑपरेंड्स को पहले आदिम में परिवर्तित किया जाता है, फिर तुलना करने से पहले उसी प्रकार से।

typeof null returns "object"

जब ऑब्जेक्ट ऑब्जेक्ट जावास्क्रिप्ट होता है तो ऑब्जेक्ट को स्ट्रिंग करने की कोशिश करता है (यानी शून्य) निम्नलिखित कदम उठाए जाते हैं ( ECMAScript 2015 ):

  1. यदि PreferredTypeपारित नहीं किया गया था, तो hint"डिफ़ॉल्ट" होने दें ।
  2. वरना अगर PreferredTypeहै hintस्ट्रिंग, चलो hintहो "स्ट्रिंग"।
  3. वरना PreferredTypeहै hintसंख्या, चलो hint"संख्या" हो।
  4. चलो exoticToPrimहो GetMethod(input, @@toPrimitive)
  5. ReturnIfAbrupt(exoticToPrim)
  6. यदि exoticToPrimअपरिभाषित नहीं है, तो
    a) परिणाम दें Call(exoticToPrim, input, «hint»)
    बी) ReturnIfAbrupt(result)
    c) यदि Type(result)ऑब्जेक्ट नहीं है, तो परिणाम लौटाएं।
    d) टाइप टाइप अपवाद को फेंक दें।
  7. यदि hint"डिफ़ॉल्ट" है, तो hint"संख्या" बनें।
  8. वापसी OrdinaryToPrimitive(input,hint)

संकेत के लिए अनुमत मान "डिफ़ॉल्ट", "संख्या" और "स्ट्रिंग" हैं। दिनांक ऑब्जेक्ट, बिल्ट-इन ECMAScript ऑब्जेक्ट के बीच अद्वितीय हैं, जिसमें वे "डिफ़ॉल्ट" को "स्ट्रिंग" के बराबर मानते हैं। अन्य सभी अंतर्निहित ईसीएमएस्क्रिप्ट ऑब्जेक्ट "डिफ़ॉल्ट" को "संख्या" के बराबर मानते हैं । ( ECMAScript 20.3.4.45 )

इसलिए मुझे लगता है कि null0 में परिवर्तित।


1

मुझे भी यही समस्या थी !!। वर्तमान में मेरा एकमात्र समाधान अलग करना है।

var a = null;
var b = undefined;

if (a===0||a>0){ } //return false  !work!
if (b===0||b>0){ } //return false  !work!

//but 
if (a>=0){ } //return true !

इसके बजाय यह करने के लिए स्पष्ट हो सकता है if (a!=null && a>=0):। यह केवल >=अपने आप से नहीं करने का कारण स्पष्ट करता है: "एक अशक्त (या अपरिभाषित, जो '== अशक्त') भी हो सकता है"।
टूलमेकरसेव

0
console.log( null > 0 );  // (1) false
console.log( null == 0 ); // (2) false
console.log( null >= 0 ); // (3) true

गणितीय, यह अजीब है। अंतिम परिणाम में कहा गया है कि "शून्य से अधिक या शून्य के बराबर है", इसलिए ऊपर की तुलनाओं में से एक में यह सच होना चाहिए, लेकिन वे दोनों झूठे हैं।

कारण यह है कि एक समानता की जांच ==और तुलना > < >= <=अलग तरह से काम करती है। तुलना शून्य को एक संख्या में बदल देती है, इसे उपचार मानती है 0। इसलिए (3) null >= 0है trueऔर (1) null > 0है false

दूसरी ओर, समानता की जाँच होती ==है undefinedऔर nullइसे ऐसे परिभाषित किया जाता है, जैसे बिना किसी रूपांतरण के, वे एक-दूसरे के बराबर होती हैं और किसी अन्य चीज़ के बराबर नहीं होती हैं। इसलिए (2) null == 0है false

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