खाली सरणियाँ एक ही समय में समान सत्य और असत्य लगती हैं


201

खाली सरणियाँ सत्य हैं, लेकिन वे झूठी के बराबर भी हैं।

var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??");

मुझे लगता है कि यह समानता ऑपरेटर द्वारा संचालित निहित रूपांतरण के कारण है।

क्या कोई समझा सकता है कि पर्दे के पीछे क्या चल रहा है?


1
यहाँ एक समान धागा है जिसे इस मुद्दे पर कुछ प्रकाश डालना चाहिए: stackoverflow.com/questions/4226101/…
Rion Williams

2
ध्यान दें, जो arr == trueसच का मूल्यांकन नहीं करता है ;-)
माइकल क्रेलिन - हैकर 20

5
वाह ... जब आपने सोचा था कि आप यह सब नीचे था।
हर्पो

3
जावास्क्रिप्ट टाइप जबरदस्ती डब्ल्यूटीएफ से बचने के लिए, सख्त समानता ऑपेरेटर का उपयोग करें ===। फिर यदि आप किसी सरणी की शून्यता का परीक्षण करना चाहते हैं, तो उपयोग करेंarr === []
DjbbZ

17
यदि आप किसी सरणी के खालीपन का परीक्षण नहीं करना चाहते हैं arr === [], तो इसका उपयोग न करें , क्योंकि हमेशा गलत वापस आ जाएगा, क्योंकि दाईं ओर एक नया सरणी है, और बाईं ओर चर आपके द्वारा बनाई गई किसी चीज़ का संदर्भ नहीं दे सकता है। परीक्षण शून्यता को देखते हुए किया जाना चाहिए arr.length === 0
काइल बेकर

जवाबों:


274

आप यहां विभिन्न चीजों का परीक्षण कर रहे हैं।

if (arr) ऑब्जेक्ट पर कॉल किया गया (Array is JS में ऑब्जेक्ट का उदाहरण है) जाँच करेगा कि ऑब्जेक्ट मौजूद है या नहीं और सही / गलत है।

जब आप कॉल करते हैं तो if (arr == false)आप इस ऑब्जेक्ट के मूल्यों और आदिम falseमूल्य की तुलना करते हैं । आंतरिक रूप से, arr.toString()कहा जाता है, जो एक खाली स्ट्रिंग लौटाता है""

ऐसा इसलिए है क्योंकि toStringएरे रिटर्न पर कॉल किया जाता है Array.join(), और खाली स्ट्रिंग जावास्क्रिप्ट में गलत मूल्यों में से एक है।


2
क्या आप बता सकते हैं कि Boolean([])रिटर्न क्यों true?
देवी

11
जेएस में सम्मेलन द्वारा, यदि वस्तुओं को बूलियन के लिए मजबूर किया जाता है, तो उन्हें हमेशा TRUE के लिए मजबूर किया जाता है। "बूलियन संदर्भ" तालिका को यहां देखें: javascript.info/tutorial/object-conversion
Niki

2
@ जावास्क्रिप्ट में सभी वस्तुएँ सत्य हैं, इसलिए बूलियन में किसी भी वस्तु को परिवर्तित करना सत्य है। देखें 2ality.com/2013/08/objects-truthy.html
थॉमसन

62

लाइन के बारे में:

if (arr == false) console.log("It's false!");

शायद ये मदद करेंगे:

console.log(0 == false) // true
console.log([] == 0) // true
console.log([] == "") // true

मेरा मानना ​​है कि ऐसा हो रहा है कि बूलियन falseको 0किसी वस्तु (बाएं हाथ की ओर) के साथ तुलना करने के लिए मजबूर किया जाता है । ऑब्जेक्ट को एक स्ट्रिंग (खाली स्ट्रिंग) के लिए मजबूर किया जाता है। फिर, खाली स्ट्रिंग को एक संख्या में, साथ ही साथ शून्य में ज़ब्त किया जाता है। और इसलिए अंतिम तुलना 0== है 0, जो है true

संपादित करें: यह कैसे काम करता है, इस पर विवरण के लिए कल्पना के इस भाग को देखें ।

नियम # 1 पर शुरू होने वाला यहां है:

1. यदि टाइप (x) टाइप (y) से अलग है, तो चरण 14 पर जाएं।

लागू होने वाला अगला नियम # 19 है:

19. यदि टाइप (y) बूलियन है, तो तुलना का परिणाम x == ToNumber (y) वापस करें।

का परिणाम ToNumber(false)है 0, इसलिए अब हमारे पास है:

[] == 0

फिर से, नियम # 1 हमें # 14 कदम पर कूदने के लिए कहता है, लेकिन वास्तव में लागू होने वाला अगला चरण # 21 है:

21. यदि टाइप (x) ऑब्जेक्ट है और टाइप (y) या तो स्ट्रिंग या संख्या है, तो तुलनात्मक परिणाम (रिटर्न) का परिणाम लौटाएं (x) == y।

ToPrimitive([])रिक्त स्ट्रिंग का परिणाम है, इसलिए अब हमारे पास है:

"" == 0

फिर से, नियम # 1 हमें # 14 चरण पर जाने के लिए कहता है, लेकिन अगला चरण वास्तव में # 17 पर लागू होता है:

17. यदि टाइप (x) स्ट्रिंग है और टाइप (y) नंबर है, तो तुलना करने का परिणाम लौटाएं ToNumber (x) = y।

का परिणाम ToNumber("")है 0, जो हमें छोड़ देता है:

0 == 0

अब, दोनों मान समान हैं, इसलिए चरण # 1 से # 7 तक जारी रहते हैं, जो कहता है:

7. यदि x y के समान संख्या मान है, तो सही लौटें।

तो, हम लौटते हैं true

संक्षेप में:

ToNumber(ToPrimitive([])) == ToNumber(false)

2
महान संदर्भ! भ्रम से बचने के लिए, यह उल्लेख करना उपयोगी हो सकता है कि कारण "लागू होने वाला अगला नियम # 19" है, हालांकि नियम # 1 कहता है कि "चरण 14 पर जाएं", क्योंकि चरण 14-18 चरण के प्रकारों से मेल नहीं खाते हैं मूल्यों की तुलना की जा रही है।
बीन

2
अच्छी व्याख्या। यह मेरे लिए हैरान करने वाला है कि खाली सरणियों [] == 0को सत्य माना जाता है, 0 को गलत, और फिर भी सत्य है। मुझे लगता है कि यह कल्पना के आपके स्पष्टीकरण के आधार पर कैसे होता है, लेकिन यह तार्किक दृष्टिकोण से विषम भाषा व्यवहार जैसा लगता है।
bigh_29

7

वेन के उत्तर के पूरक के लिए और यह समझाने की कोशिश करने के लिए कि ToPrimitive([])रिटर्न क्यों है "", यह 'क्यों' प्रश्न के दो संभावित प्रकारों के जवाबों पर विचार करने के लायक है। पहला प्रकार का उत्तर है: "क्योंकि विनिर्देश कहता है कि यह कैसे जावास्क्रिप्ट व्यवहार करेगा।" ES5 कल्पना में, खंड 9.1 , जो एक वस्तु के लिए डिफ़ॉल्ट मूल्य के रूप में ToPrimitive के परिणाम का वर्णन करता है:

ऑब्जेक्ट का डिफ़ॉल्ट मान [[DefaultValue]] आंतरिक विधि को कॉल करके प्राप्त किया जाता है, वैकल्पिक संकेत PreferredType से गुजर रहा है।

धारा 8.12.8[[DefaultValue]] विधि का वर्णन करती है। यह विधि एक तर्क के रूप में "संकेत" लेती है, और संकेत या तो स्ट्रिंग या संख्या हो सकती है। कुछ विवरणों के साथ वितरण करके मामले को सरल बनाने के लिए, यदि संकेत स्ट्रिंग है, तो यदि मौजूद है तो [[DefaultValue]]मान toString()लौटाता है और एक आदिम मान लौटाता है और अन्यथा का मान लौटाता है valueOf()। संकेत संख्या, की प्राथमिकताओं है toString()और valueOf()कि इतने उलट कर रहे हैं valueOf()पहले कहा जाता है और उसके मान दिया है, तो यह एक आदिम है। इस प्रकार, चाहे [[DefaultValue]]वह परिणाम लौटाए toString()या valueOf()वस्तु के लिए निर्दिष्ट PreferredType पर निर्भर करता है या नहीं और ये फ़ंक्शन आदिम मान लौटाते हैं या नहीं।

डिफ़ॉल्ट valueOf()ऑब्जेक्ट विधि सिर्फ ऑब्जेक्ट को ही लौटाती है, जिसका अर्थ है कि जब तक कोई वर्ग डिफ़ॉल्ट विधि को ओवरराइड नहीं करता है, तब तक valueOf()केवल ऑब्जेक्ट ही वापस आता है। यह मामला है Array[].valueOf()वस्तु को []ही लौटाता है। चूंकि एक Arrayवस्तु एक आदिम नहीं है, [[DefaultValue]]संकेत अप्रासंगिक है: एक सरणी के लिए वापसी मूल्य का मूल्य होगा toString()

डेविड फ्लैनगन के जावास्क्रिप्ट को उद्धृत करने के लिए : निश्चित गाइड , जो, एक शानदार किताब है, जो इस प्रकार के सवालों के जवाब पाने के लिए हर किसी की पहली जगह होनी चाहिए:

इस ऑब्जेक्ट-टू-नंबर रूपांतरण का विवरण बताता है कि खाली सरणी संख्या 0 में क्यों परिवर्तित होती है और एकल तत्व वाला सरणी भी संख्या में परिवर्तित हो सकता है। एरे को डिफ़ॉल्ट मान (ओफ़) विधि विरासत में मिली है जो एक वस्तु को एक आदिम मूल्य के बजाय लौटाती है, इसलिए सरणी-टू-नंबर रूपांतरण स्ट्रींग () विधि पर निर्भर करता है। खाली सरणियाँ खाली स्ट्रिंग में परिवर्तित होती हैं। और खाली स्ट्रिंग संख्या 0. में परिवर्तित हो जाती है। एकल तत्व वाला एक सरणी उसी स्ट्रिंग में परिवर्तित होता है जो एक तत्व करता है। यदि किसी सरणी में एक एकल संख्या होती है, तो वह संख्या एक स्ट्रिंग में बदल जाती है, और फिर एक नंबर पर वापस आ जाती है।

"क्यों" प्रश्न के दूसरे प्रकार के उत्तर, "क्योंकि कल्पना कहती है" के अलावा, इस बात के लिए कुछ स्पष्टीकरण देता है कि व्यवहार डिजाइन के दृष्टिकोण से क्यों समझ में आता है। इस मुद्दे पर मैं केवल अटकलें लगा सकता हूं। सबसे पहले, एक सरणी को एक संख्या में कैसे परिवर्तित किया जाएगा? एकमात्र समझदार संभावना जिसे मैं सोच सकता हूं कि खाली सरणी को 0 और किसी गैर-रिक्त सरणी में 1 में परिवर्तित किया जाएगा। लेकिन जैसा कि वेन के उत्तर से पता चला है, एक खाली सरणी किसी भी तरह की तुलना के लिए 0 में परिवर्तित हो जाएगी। इससे परे, Array.valueOf () के लिए एक समझदार आदिम वापसी मूल्य के बारे में सोचना मुश्किल है। तो कोई यह तर्क दे सकता है कि यह केवल Array.valueOf()डिफ़ॉल्ट होने के लिए अधिक समझ में आता है और एरे को खुद लौटाता है, अग्रणीtoString() एरियर को परिणामस्वरूप ToPrimitive द्वारा उपयोग किया जाता है। यह सिर्फ एक संख्या के बजाय एक ऐरे को एक स्ट्रिंग में बदलने के लिए अधिक समझ में आता है।

इसके अलावा, जैसा कि फ्लैनगन उद्धरण द्वारा संकेत दिया गया है, यह डिजाइन निर्णय कुछ प्रकार के लाभकारी व्यवहारों को सक्षम करता है। उदाहरण के लिए:

var a = [17], b = 17, c=1;
console.log(a==b);      // <= true
console.log(a==c);      // <= false

यह व्यवहार आपको एकल-तत्व सरणी की संख्या से तुलना करने और अपेक्षित परिणाम प्राप्त करने की अनुमति देता है।


इस उत्तर के लिए धन्यवाद, यह काफी विस्तृत व्याख्या है कि प्रश्न का अभाव है।
एस्टस फ्लास्क

3
console.log('-- types: undefined, boolean, number, string, object --');
console.log(typeof undefined);  // undefined
console.log(typeof null);       // object
console.log(typeof NaN);        // number
console.log(typeof false);      // boolean
console.log(typeof 0);          // number
console.log(typeof "");         // string
console.log(typeof []);         // object
console.log(typeof {});         // object

console.log('-- Different values: NotExist, Falsy, NaN, [], {} --');
console.log('-- 1. NotExist values: undefined, null have same value --');
console.log(undefined == null); // true

console.log('-- 2. Falsy values: false, 0, "" have same value --');
console.log(false == 0);        // true
console.log(false == "");       // true
console.log(0 == "");           // true

console.log('-- 3. !NotExist, !Falsy, and !NaN return true --');
console.log(!undefined);        // true
console.log(!null);             // true

console.log(!false);            // true
console.log(!"");               // true
console.log(!0);                // true

console.log(!NaN);              // true

console.log('-- 4. [] is not falsy, but [] == false because [].toString() returns "" --');
console.log(false == []);       // true
console.log([].toString());     // ""

console.log(![]);               // false

console.log('-- 5. {} is not falsy, and {} != false, because {}.toString() returns "[object Object]" --');
console.log(false == {});       // false
console.log({}.toString());     // [object Object]

console.log(!{});               // false

console.log('-- Comparing --');
console.log('-- 1. string will be converted to number or NaN when comparing with a number, and "" will be converted to 0 --');
console.log(12 < "2");          // false
console.log("12" < "2");        // true
console.log("" < 2);            // true

console.log('-- 2. NaN can not be compared with any value, even if NaN itself, always return false --');
console.log(NaN == NaN);        // false

console.log(NaN == null);       // false
console.log(NaN == undefined);  // false
console.log(0 <= NaN);          // false
console.log(0 >= NaN);          // false
console.log(undefined <= NaN);  // false
console.log(undefined >= NaN);  // false
console.log(null <= NaN);       // false
console.log(null >= NaN);       // false

console.log(2 <= "2a");         // false, since "2a" is converted to NaN
console.log(2 >= "2a");         // false, since "2a" is converted to NaN

console.log('-- 3. undefined can only == null and == undefined, and can not do any other comparing even if <= undefined --');
console.log(undefined == null);         // true
console.log(undefined == undefined);    // true

console.log(undefined == "");           // false
console.log(undefined == false);        // false
console.log(undefined <= undefined);    // false
console.log(undefined <= null);         // false
console.log(undefined >= null);         // false
console.log(0 <= undefined);            // false
console.log(0 >= undefined);            // false

console.log('-- 4. null will be converted to "" when <, >, <=, >= comparing --');
console.log(12 <= null);        // false
console.log(12 >= null);        // true
console.log("12" <= null);      // false
console.log("12" >= null);      // true

console.log(0 == null);         // false
console.log("" == null);        // false

console.log('-- 5. object, including {}, [], will be call toString() when comparing --');
console.log(12 < {});           // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log(12 > {});           // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log("[a" < {});         // true, since {}.toString() is "[object Object]"
console.log("[a" > {});         // false, since {}.toString() is "[object Object]"
console.log(12 < []);           // false, since {}.toString() is "", and then converted to 0
console.log(12 > []);           // true, since {}.toString() is "", and then converted to 0
console.log("[a" < []);         // false, since {}.toString() is ""
console.log("[a" > []);         // true, since {}.toString() is ""

console.log('-- 6. According to 4 and 5, we can get below weird result: --');
console.log(null < []);         // false
console.log(null > []);         // false
console.log(null == []);        // false
console.log(null <= []);        // true
console.log(null >= []);        // true

2

अगर (गिरफ्तार), तो हमेशा मूल्यांकन किया जाता है (ToBoolean) सही है अगर गिरफ्तारी एक वस्तु है क्योंकि जावास्क्रिप्ट में सभी ऑब्जेक्ट सत्य हैं । (नल कोई वस्तु नहीं है!)

[] == falseपुनरावृत्ति दृष्टिकोण में मूल्यांकन किया है। सबसे पहले, यदि एक पक्ष ==आदिम है और दूसरा ऑब्जेक्ट है, तो यह ऑब्जेक्ट को सबसे पहले आदिम में कनवर्ट करता है, फिर दोनों पक्षों को संख्या में परिवर्तित करता है यदि दोनों पक्ष नहीं हैं string( दोनों पक्षों के तार होने पर स्ट्रिंग तुलना का उपयोग किया जाता है)। तो तुलना इसकी तरह है, [] == false-> '' == false-> 0 == 0-> true


2

उदाहरण:

const array = []
const boolValueOfArray = !!array // true

ऐसा इसलिए होता है

ToNumber(ToPrimitive([])) == ToNumber(false)  
  1. []खाली Arrayवस्तु है → ToPrimitive([])→ "" → ToNumber("")0
  2. ToNumber(false) → 0
  3. 0 == 0 → सच

1

तत्वों के साथ एक सरणी (भले ही 0, झूठी या किसी अन्य खाली सरणी), हमेशा trueसार समानता तुलना का उपयोग करने का संकल्प करता है ==

1. [] == false; // true, because an empty array has nothing to be truthy about
2. [2] == false; // false because it has at least 1 item
3. [false] == false; // also false because false is still an item
4. [[]] == false; // false, empty array is still an item

लेकिन एक सख्त समानता तुलना का उपयोग करते हुए ===, आप चर की सामग्री के साथ-साथ इसके डेटा प्रकार का मूल्यांकन करने का प्रयास कर रहे हैं, इसीलिए:

1. [] === false; // false, because an array (regardless of empty or not) is not strictly comparable to boolean `false`
2. [] === true; // false, same as above, cannot strictly compare [] to boolean `true`
3. [[]] === false; // true, because see #1

-1

list = []वर्तमान में संदर्भित सरणी के तत्वों का उपयोग करके या हटाकर , आप इसे एक नए सरणी में संदर्भित करके एक जावास्क्रिप्ट ऐरे को खाली कर सकते हैं list.length = 0

स्रोत: जावास्क्रिप्ट खाली एरे


-2

उपरोक्त में से किसी ने भी मेरी मदद नहीं की, जब नॉकआउट.जेएस मैपिंग प्लगइन का उपयोग करने की कोशिश की गई, शायद तब से "खाली सरणी" वास्तव में खाली नहीं है।

मैंने उपयोग करना समाप्त कर दिया: data-bind="if: arr().length"जिसने चाल चली।

यह नॉकआउट के लिए विशिष्ट है, ओपी का सवाल नहीं है, लेकिन शायद यह किसी अन्य व्यक्ति को यहां समान स्थिति में ब्राउज़ करने में मदद करेगा।


यह उत्तर संबंधित नहीं है
फौजवाद

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