2017-06-01 10 views
10

लंबाई 1 की सरणी के साथ 0 की तुलना क्यों की जाती है जबकि यह 2 या उससे अधिक की सरणी लंबाई के लिए झूठी होती है? उदाहरण के लिए,लंबाई 1 या उससे अधिक की सरणी के साथ झूठ बोलते समय लंबाई 1 की सरणी के साथ एक पूर्णांक की तुलना क्यों सच है?

var a=[] //undefined 
0<a //returns false 
a.push(1) // [1] 
0<a // returns true 
a.push(2) // [1, 2] 
0<a // return false 
a.push(3) // [1, 2, 3] 
0<a // return false 

उत्तर

9

मूल रूप से आप एक implicid जैसे रूपांतरण, पहले toString,

Array वस्तु को ओवरराइड करता है Object की toString विधि मिलता है। ऐरे ऑब्जेक्ट्स के लिए, toString विधि सरणी में शामिल होती है और एक स्ट्रिंग देता है जिसमें प्रत्येक सरणी तत्व को अल्पविराम से अलग किया जाता है।

जावास्क्रिप्ट स्वचालित रूप से toString विधि को कॉल करता है जब किसी सरणी को पाठ मान के रूप में प्रदर्शित किया जाना चाहिए या किसी सरणी को स्ट्रिंग कॉन्सटेनेशन में संदर्भित किया जाता है।

जैसे join काम करता है और फिर इसे संख्या में परिवर्तित कर दिया जाता है।

what you do what you get result array  string  number 
------------ ------------ ------ --------- -------- ---------- 
var a = []; 
0 < a   0 < 0   false []  -> ''  -> 0 
a.push(1); 
0 < a   0 < 1   true [1]  -> '1'  -> 1 
a.push(2); 
0 < a   0 < NaN  false [1, 2] -> '1,2' -> NaN 
a.push(3); 
0 < a   0 < NaN  false [1, 2, 3] -> '1,2,3' -> NaN 
+1

क्या आपके पास कोई संदर्भ है कि इस मामले में जावास्क्रिप्ट पहले स्ट्रिंग में रूपांतरण करता है, और फिर संख्या में? – trincot

+0

Obligatory [jsF ** * स्पष्टीकरण] (http://thedailywtf.com/articles/bidding-on-security) – ryanyuyu

+0

@trincot, ईसीएमए 262 वी 6 [7.2.11 सार संबंधपरक तुलना] (https://www.ecma-international.org /ecma-262/6.0/#sec-abstract-relational-comparison), यह पहले एक आदिम मान प्राप्त करने का प्रयास करता है, जो टूस्ट्रिंग द्वारा पहुंचा जा सकता है। –

0

आप सरणी के lenght की तुलना करना चाहते हैं, तो a.length का उपयोग करें।

1

यदि आप उपरोक्त प्रत्येक पंक्ति के बाद किसी संख्या के रूप में सरणी को चेक करते हैं तो यह आपको उत्तर देता है। संख्या - अगर आप अपने सरणी में केवल 1 तत्व है जावास्क्रिप्ट याद रखें तुलना

Number(a); //insert this after each line 
+0

और क्यों 'पुश (2) 'और' पुश (3)' ना ''रिटर्न' करता है? – doutriforce

+0

'console.log (a.toString(), संख्या (a.toString())' – epascarello

0

के दौरान कुछ typecasting करता जे एस में, जे एस, तत्व की तरह अपने मूल्य की गणना होती है आपके मामले में। उदाहरण के लिए :

var b[] 
b.push(8); 
b == 8 //true (but b === 8 is false!) 

और अगर आप सरणी में अधिक तो 1 तत्व है, सरणी प्रकार सरणी [संख्या] है और यह संख्या से अलग है और उसकी वजह से आप एक संख्या की तुलना नहीं कर सकते ।

Thats आप कोड में क्यों तुम्हारे जाने के बाद कार्य करें:

var a=[] 
0<a 
a.push(1) 
0<a 

आप एक मूल्य क्योंकि सच मिल अब "1" और है कि बड़े तो 0. लेकिन है, अगले धक्का मूल्य [1 के बाद, 2] और यह एक संख्या (NaN) नहीं है और यही कारण है कि आप झूठी क्यों हैं।

1

जे एस की तरह एक शिथिल टाइप किया भाषा आप कैसे एक सरणी की तरह एक परिवर्तनशील प्रकार अपरिवर्तनीय प्रकार में coerces पर ध्यान देना है में। मूल रूप से [1,2]"1,2" बन जाता है।

तो [1,2] == "1,2" // <- true

+0

यह वास्तव में इस बात से संबंधित नहीं है कि कोई मूल्य अपरिवर्तनीय है या नहीं। यहां तक ​​कि जब ऑब्जेक्ट 'ऑब्जेक्ट.फ्रीज़' के साथ अपरिवर्तनीय बना दिया जाता है तब भी आपको इस प्रकार का जबरदस्त मिल जाएगा। – trincot

+0

हाँ आप सही हैं। मेरा मतलब यह था कि टाइप जबरन अपरिवर्तनीय प्रकार की ओर है। – Redu

+0

मुझे लगता है कि आपका मतलब "आदिम" है, इतना "अपरिवर्तनीय" नहीं। अपरिवर्तनीय वस्तुएं भी हैं, और जबरन उनके प्रति नहीं है। – trincot

0

तुलना के लिए, जावास्क्रिप्ट संख्या आम तौर पर (पसंदीदा) में ऑपरेंड कन्वर्ट करने के लिए कोशिश करता है। इस उदाहरण को

देखो:

console.log("test" == true);//false 
console.log("test" == false);//false 

क्यों? क्योंकि "परीक्षण" को संख्या में परिवर्तित करने का प्रयास किया जाता है, इसलिए संख्या ("परीक्षण") NaN देता है और NaN या तो सत्य या गलत के बराबर नहीं है। इसी तरह,

0<a becomes 0 < Number(a) becomes 0 < 0 returns "false". 

एक विशेष मामले के रूप में, जब सरणी एक तत्व, Number कि मजबूर करने के लिए एक नंबर करने में सक्षम है, लेकिन जब आप एक से अधिक तत्व जोड़ दिया है, क्या संख्या दी जानी चाहिए? उस स्थिति में, संख्या (एआर) NaN बन जाती है और फिर 0 NaN से कम नहीं है।

3

संख्या और एक सरणी के बीच तुलना एक प्रकार रूपांतरण को ट्रिगर करेगा। एक्मास्क्रिप्ट विनिर्देश section 7.1.3 में इसके लिए नियम निर्धारित करता है। इन नियमों के अनुसार, संख्या एक और डेटा प्रकार में परिवर्तित नहीं किया जाता है, लेकिन वस्तु (एक सरणी एक वस्तु है) एक रूपांतरण है कि इस तरह से चला जाता है के अधीन किया जाएगा:

  1. चलो primValue ToPrimitive हो (तर्क, संकेत संख्या)।
  2. वापसी करने के लिए संख्या (primValue)।

ToPrimitive समारोह section 7.1.1 में वर्णित है:

  1. exoticToPrim चलो GetMethod हो (इनपुट, @@ toPrimitive)।

@@toPrimitive एक प्रतीक है, तो आप Symbol.toPrimitive के रूप में का उपयोग जो है। बात यह है कि Array इस संपत्ति नहीं है, और इसलिए प्रक्रिया इस कदम के साथ जारी है:

  1. वापसी OrdinaryToPrimitive (इनपुट, संकेत)।

सार आपरेशन OrdinaryToPrimitive तर्क हे और संकेत के साथ कहा जाता है जब, निम्नलिखित कदम उठाए जाते हैं:

  1. तो संकेत कि "स्ट्रिंग", तो
        ए। विधि नाम हो सकता है «" toString ", मूल्य" »।
  2. अन्य,
        ए। विधि नाम हो सकता है «" वैल्यू "," टूस्ट्रिंग "»।

रूप संकेत कि "संख्या", हम दूसरे मामले में कर रहे हैं। अगले चरण बताते हैं कि इन तरीकों को क्रम में लागू किया गया है।

अब, Array.prototype.valueOf सिर्फ सरणी स्वयं लौटाता है, इसलिए निम्न उप-चरण वापस नहीं आएगा, क्योंकि टाइप ऑब्जेक्ट (अर्थात् ऐरे) है।

5.c.iii हैं प्रकार (परिणाम) वस्तु नहीं है, परिणाम लौट आते हैं।

परिणामस्वरूप फॉलबैक में प्रवेश होता है, और toString को ऐरे पर बुलाया जाता है।

तो सरणी स्ट्रिंग में परिवर्तित हो जाती है। यह शीर्ष पर सूचीबद्ध दो चरणों के पहले का परिणाम है:

  1. primValue हो ToPrimitive चलो (तर्क, संकेत संख्या)।
  2. वापसी करने के लिए संख्या (primValue)।

दूसरे चरण के लिए आसान है: स्ट्रिंग तो संख्या है, जो section 7.1.3.1 में वर्णन किया गया में बदल जाती है।

Array.prototype.toString विधि के रूप में एक अल्पविराम से अलग सूची बनाता है, जैसे ही एक सरणी में एक से अधिक तत्व होते हैं, ये स्ट्रिंग निश्चित रूप से अमान्य संख्या बन जाती हैं। जैसा कि चश्मे में उल्लिखित है, तो वापसी मूल्य NaN है।

NaN के साथ तुलना false देता है, जो आपको प्राप्त होने वाले आउटपुट को बताता है।

संबंधित मुद्दे