जावास्क्रिप्ट में सच का मूल्यांकन {{} [सच] क्यों होता है?


131

{}[true]है [true]और ![true]होना चाहिए false

तो !{}[true]मूल्यांकन क्यों करता है true?


30
var o = {}; o[true] === undefined
अज़

2
इस स्पष्टीकरण की संभावना इस पिछले प्रश्न
IMSoP

45
"क्योंकि जावास्क्रिप्ट मूर्खतापूर्ण है" शायद वह जवाब नहीं है जिसे आप खोज रहे हैं।
जॉर्ज

2
जैसा कि उल्लेख किया गया है, यदि आप {}[true] === [true]एक कंसोल से प्राप्त कर रहे हैं, तो ऐसा इसलिए है क्योंकि यह {}एक खाली कोड ब्लॉक के रूप में माना जाता है , एक वस्तु नहीं।
azz

3
अगर यह मदद कर सकते हैं, तुलना करने की कोशिश {}और ({})अपने कंसोल (या में {}[true]और ({})[true])। इसके अलावा, जैसा कि किसी ने भी इसका उल्लेख नहीं किया है, वस्तु [सत्य] का मूल्यांकन वस्तु ["सच"] के लिए किया जाता है।
BiAiB

जवाबों:


172

मेरा मानना ​​है कि क्योंकि सादे {}[true]को एक खाली स्टेटमेंट ब्लॉक (वस्तु नहीं शाब्दिक) के रूप में रखा गया है true, जिसके बाद एक सरणी होती है , जो है true

दूसरी ओर, !ऑपरेटर को लागू करने से पार्सर की व्याख्या {}एक वस्तु शाब्दिक के रूप में होती है, इसलिए निम्नलिखित {}[true]एक सदस्य का उपयोग करता है जो वापस लौटता है undefined, और !{}[true]वास्तव में true(जैसा !undefinedहै true)।


25
तथ्य यह है कि अपरिभाषित सच है, दूसरी ओर, अभी भी अक्षम्य है।
दुष्टकंडीबाग

87
@evilcandybag: यह बिल्कुल नहीं है। undefinedमिथ्या है (कुछ ऐसा है जिस पर हम अक्सर भरोसा करते हैं - if (obj.maybeExists) ...), इसलिए यह सही तार्किक अर्थ बनाता है जो !undefinedसच है।
josh3736

8
@Josh, मुझे लगता है कि evilcandybag एक व्यवहार के लिए समान पसंद करेंगे nullके साथ, कुछ भाषाओं में !undefinedकरने के लिए बराबर किया जा रहा है undefined। हालांकि जावास्क्रिप्ट में ऐसा नहीं है।
Frédéric Hamidi

6
@evilcandybag: यह केवल यह कहने के लिए तार्किक समझ में आता है कि कुछ ऐसा है not undefined( !undefined) इसलिए परिभाषित किया जाना चाहिए। यदि कुछ परिभाषित किया जाता है तो इसकी व्याख्या आमतौर पर की जाती है true
ऊज मीस्टर

7
@ क्रंचर यदि a अपरिभाषित है, और b अपरिभाषित है, तो हम संभवतः कैसे जान सकते हैं कि a = = b? विशेष रूप से जब दो चर की एकमात्र ज्ञात विशेषता बिल्कुल समान है।
LJ2

44

क्योंकि {}[true]वापस नहीं आता है true, लेकिन undefined, और undefinedमूल्यांकन किया जाता है false:

http://jsfiddle.net/67GEu/

'use strict';
var b = {}[true];
alert(b); // undefined
b = !{}[true];
alert(b); // true

21
यदि आप {}[true]एक कंसोल में मूल्यांकन करते हैं , तो आप प्राप्त करते हैं [true], क्योंकि {}एक खाली कोड ब्लॉक के रूप में व्याख्या की जाती है, एक वस्तु नहीं। यह संदर्भ और अस्पष्टता के बारे में है {}
IMSoP

1
@IMSoP लेकिन इसका {key:"value"}[1,2,3];मूल्यांकन भी क्यों करता है [1,2,3]?
t.niese

3
@ t.niese, क्योंकि यह एक लेबल ( key:) और एक स्ट्रिंग शाब्दिक ( "value"), जिसमें एक सरणी द्वारा पीछा किया गया है, एक बयान ब्लॉक के रूप में पार्स किया गया है। पार्सर अभी भी एक वस्तु शाब्दिक नहीं देखता है।
फ्रैडरिक हमीदी

1
@ Frédéric Hamidi आह हाँ, यह है। मैंने लेबल लेबल ^ ^
t.niese

1
@dooxe अन्य उत्तर पढ़ें; यह सब उस संदर्भ के बारे में है जिसमें इसकी व्याख्या की गई है। आप में लपेट हैं alert()या console.log(), या एक चर के लिए असाइन करें, आप संदर्भ बदल रहे हैं, जो है के रूप में एक कंसोल में अपने आप ही आपके द्वारा लिखे गए कारण है कि यह एक ही तरह से व्यवहार नहीं करता है।
IMSoP

27

इसलिये

{}[true]

मूल्यांकन करता है undefined, और !undefinedहै true

@Schlingel से:

trueकुंजी के रूप में और {}हैश मानचित्र के रूप में उपयोग किया जाता है । वहाँ कुंजी के साथ एक संपत्ति मौजूद नहीं है trueइसलिए यह वापस आ जाता है undefined। अपेक्षा के अनुरूप नहीं undefinedहै true

कंसोल सत्र ( Node.js [0.10.17] ):

> {}[true]
undefined
> !{}[true]
true
> [true]
[ true ]
> ![true]
false
>

हालाँकि, Google Chrome कंसोल में:

> !{}[true]
true

तो, कोई विसंगतियां नहीं। आप शायद JavaScript VM के पुराने संस्करण का उपयोग कर रहे हैं। उन लोगों के लिए जिन्हें और सबूत चाहिए:

यहां छवि विवरण दर्ज करें

अपडेट करें

फ़ायरफ़ॉक्स के साथ , यह भी मूल्यांकन करता है true:

यहां छवि विवरण दर्ज करें


यदि आप eval('{}[true]')इसे सांत्वना के लिए करते हैं या टाइप करते हैं तो नहीं । फिर जैसे als {}"test"है testया यहां तक कि {key:"value"}"test"है test
t.niese

दिलचस्प है कि आप किस js इंजन का परीक्षण करते हैं?
t.niese

@ t.niese मैंने इसे केवल अपने नोड कंसोल में टाइप किया, और यही मुझे मिला।
गेम्स ब्रेनियक

बस जिज्ञासा के लिए। क्या आपके {}[true];साथ (के लिए ;) वापसी होती [true]है, क्योंकि यहाँ यह करता है?
t.niese

2
डाउनवोट लोगों के लिए कारण? इस पर लगभग 8 वोटों के साथ एक समान उत्तर है, और मुझे नीचे की ओर मिलता है? मैंने गलत क्या किया?
गेम्स ब्रेनियाक

23

भ्रम का कारण आपके पहले दावे की गलतफहमी के कारण है:

{}[true] है [true]

जब आप इसे चलाते हैं तो आप जो देखते हैं वह एक अस्पष्टता का परिणाम है। जावास्क्रिप्ट में नियमों का एक निर्धारित सेट होता है कि इस तरह अस्पष्टताओं को कैसे संभालना है, और इस मामले में, यह दो अलग-अलग बयानों में एक सांकेतिक बयान के रूप में आपको जो दिखता है उसे तोड़ देता है।

इसलिए जावास्क्रिप्ट उपरोक्त कोड को दो अलग-अलग बयानों के रूप में देखता है: सबसे पहले, एक है {}, और फिर एक पूरी तरह से अलग है [true]। दूसरा कथन जो आपको परिणाम दे रहा है [true]। पहले बयान {}को पूरी तरह से नजरअंदाज कर दिया गया है।

आप निम्न प्रयास करके इसे साबित कर सकते हैं:

({}[true])

यानी पूरी वस्तु को कोष्ठक में लपेटकर दुभाषिया को एक ही कथन के रूप में पढ़ने के लिए मजबूर करना।

अब आप देखेंगे कि आपके कथन का वास्तविक मूल्य क्या है undefined। (इससे हमें अगले भाग को समझने में भी मदद मिलेगी)

अब हम जानते हैं कि आपके प्रश्न का प्रारंभिक भाग एक लाल हेरिंग है, तो चलिए प्रश्न के अंतिम भाग पर चलते हैं:

तो क्यों करता है! {} [सच] मूल्यांकन करने के लिए सच है?

यहां, हमारे पास एक ही कथन है, लेकिन !इसके सामने एक जोड़ के साथ ।

इस मामले में, जावास्क्रिप्ट के नियम इसे एक ही कथन के रूप में पूरी बात का मूल्यांकन करने के लिए कहते हैं।

जब हम पहले वाले बयान को कोष्ठक में लपेटते हैं तो क्या हुआ था, इसका संदर्भ लें; हमें मिल गया undefined। इस बार, हम प्रभावी रूप से एक ही काम कर रहे हैं, लेकिन !इसके सामने एक ही डाल रहे हैं। तो आपके कोड को सरल बनाया जा सकता है !undefined, जो कि है true

उम्मीद है कि यह थोड़ा समझाता है।

यह एक जटिल जानवर है, लेकिन यहां सीखने का सबक कंसोल में उनका मूल्यांकन करते समय, अपने बयानों के आसपास कोष्ठक का उपयोग करना है, ताकि इस तरह के हानिकारक परिणामों से बचा जा सके।


2
मुझे नहीं लगता कि {}[true]यह अवैध है, बस अस्पष्ट है । इसे या तो "खाली कोड ब्लॉक के बाद सरणी शाब्दिक" या "बिना किसी गुण के ऑब्जेक्ट ऑब्जेक्ट शाब्दिक, जिसमें से एक संपत्ति तक पहुँचा जा रहा है" के रूप में व्याख्या की जा सकती है। मुझे नहीं पता कि अगर तकनीकी रूप से एएसआई का मामला है (कई भाषाएं वहां अर्ध-उपनिवेश नहीं डालती हैं) लेकिन यह संदर्भ-संवेदनशील व्याख्या है जो इस मुद्दे का दिल है।
IMSoP

@IMSoP - टिप्पणी पोस्ट करने से पहले ही मैंने उत्तर को संपादित कर दिया था। :)
स्पडली

1
यह अभी भी कहता है "{} [सच] वास्तव में उत्तर की शुरुआत में बिल्कुल" सही नहीं है।
IMSoP

इसके अलावा, ओपी कहा नहीं " {}[true]है true" उन्होंने कहा " {}[true]है [true]जो अस्पष्ट बयान के दो वैध व्याख्याओं में से एक है",।
IMSoP

14

{}[true]है undefined। यह जानने के लिए कि यह लिखें:

a = {};
a[true] === undefined // true

या केवल:

({})[true] === undefined // true

हम जानते हैं कि !undefinedहै true


से @Benjamin Gruenbaum के जवाब :

क्रोम डवलर टूल निम्न कार्य करता है :

  try {
      if (injectCommandLineAPI && inspectedWindow.console) {
          inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
          expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {\n" + expression + "\n}";
      }
      var result = evalFunction.call(object, expression);
      if (objectGroup === "console")
          this._lastResult = result;
      return result;
  } 
  finally {
      if (injectCommandLineAPI && inspectedWindow.console)
          delete inspectedWindow.console._commandLineAPI;
  }

तो मूल रूप से, यह callअभिव्यक्ति के साथ ऑब्जेक्ट पर प्रदर्शन करता है । अभिव्यक्ति की जा रही है:

with ((window && window.console && window.console._commandLineAPI) || {}) {
    {}+{};// <-- This is your code
}

तो, जैसा कि आप देख सकते हैं, रैपिंग कोष्ठक के बिना, अभिव्यक्ति को सीधे विकसित किया जा रहा है।

अधिक जानकारी इस प्रश्न में मिल सकती है ।


10

यहाँ उत्तर अच्छे हैं, यहाँ छद्म कोड में एक खराबी है:

  • {}['whatever'] = खाली ब्लॉक, न्यूअरे ('जो भी हो) = न्यूअरे (' जो भी हो))
  • {}[true] = खाली ब्लॉक, न्यूअरे (सच) = न्यूअरे (सच)
  • !{}['whatever'] = LogicalNOT (ConvertToBool (NewObject.whatever)) = LogicalNOT (ConvertToBool (अपरिभाषित)) = LogicalNOT (गलत) = true
  • ({}['whatever']) = समूहन (NewObject.whatever) = समूहीकरण (अपरिभाषित) = अपरिभाषित

8

ऐसा इसलिए होता है क्योंकि {}आपके अर्थ में शाब्दिक प्रस्तुति नहीं है Object, लेकिन खाली स्कोप (या खाली कोड ब्लॉक):

{ var a = 1 }[true] // [true] (do the same thing)

यह बस दायरे के अंदर कोड का मूल्यांकन करता है और फिर आपको अपनी सरणी दिखाता है।

और अपने से

!{}[true]

बस इस दायरे को इंट करने और उसी एरे को सही करने के लिए कनवर्ट करता है। इस कोड में कोई बूल चेक नहीं है।

और यदि आप परिणाम की जाँच करने की कोशिश करेंगे तो आपको {}[true]अपना परिणाम मिलेगा false:

{}[true] -> [true] -> ![true] -> false

जैसा कि कोई और गुंजाइश नहीं है।

तो !अपने प्रश्न में भी ऐसा ही करें:

!function() {
   //...
}

यदि आप ऐसा करते हैं तो यह अधिक आसानी से देखा जा सकता है var x = {}; x[true]
क्रिस हेस

1
मुझे यकीन नहीं है कि आपके द्वारा "इस गुंजाइश को बढ़ाने के लिए अभिसरण" से क्या मतलब है; मुझे लगता है कि अग्रणी के साथ !यह एक खाली वस्तु के रूप में व्याख्या की जाती है, गुंजाइश नहीं है, और यह विसंगति है।
IMSoP

6
  • {} कोई भी गुण नहीं है।
  • चूँकि []किसी वस्तु का तुरंत अनुसरण होता है, इसका अर्थ है "इस नाम की एक संपत्ति तक पहुँच" और "एक सरणी बनाएँ" नहीं
  • trueएक बूलियन है, लेकिन इसे एक संपत्ति के नाम के रूप में इस्तेमाल किया जा रहा है, इसलिए इसे एक स्ट्रिंग ( "true") के लिए डाला जाता है
  • वस्तु एक संपत्ति बुलाया नहीं है true(क्योंकि यह कोई प्रॉपर्टी नहीं है) तो {}['true']हैundefined
  • !undefinedडाले undefinedएक बूलियन के लिए ( false)
  • नहीं ऑपरेटर में बदल जाता falseहै true

2
के मामले में {}[true](कोई अन्य संदर्भ के साथ), {}है कोई गुण के साथ एक वस्तु है, यह एक खाली कोड ब्लॉक है।
IMSoP


4

चलो थोड़ा और खेलते हैं!

पहले, चलो कुछ मजा करें! "

//----------#01#-----------
{}[true]; //[true]

//----------#02#-----------
var a = {}[true]; 
      console.log(a); //undefined

//----------#03#-----------
{ b: 12345 }[true]; //[true]

//----------#04#-----------
{ b: 12345 }["b"]; //evaluates to ["b"] ?!?

//----------#05#-----------
{ b: 12345 }.b; // "Unexpected token ."

//----------#06#-----------
({ b: 12345 }).b; //12345

//----------#07#-----------
var c = { b: 12345 }.b; 
      console.log(c); //12345

//----------#08#-----------
var c = { b: 12345 }["b"];
      console.log(c); //12345

//----------#09#-----------
{ true: 54321 }[true]; // "SyntaxError: Unexpected token : "

//----------#10#-----------
var d = { true: 54321 }[true]; //No error here ¬¬
      console.log(d); //54321

//----------#11#-----------
!{}[true]; // true

ठीक है, आइए एक-एक करके इन पागल व्यवहारों को समझने की कोशिश करें:

1) यहाँ, {}एक खाली कोड ब्लॉक के रूप में पार्स किया गया है। बिना असाइनमेंट, नेगशन, ग्रुपिंग (कोष्ठकों के साथ) या किसी भी वाक्य रचना जो पार्सर को इंगित करता है कि यह {}एक वस्तु शाब्दिक है, डिफ़ॉल्ट धारणा यह सोचना है कि यह केवल एक बेकार खाली ब्लॉक है।

यह इस व्यवहार का प्रमाण है:

{ alert(123) }[true]

ऊपर दिया गया कोड सामान्य रूप से अलर्ट दिखाएगा, और मूल्यांकन किया जाएगा [true], उसी तरह से {}[true]है।

अर्धविराम के बिना ब्लॉक विवरण

एक ब्लॉक-प्रकार के बयान के बाद अर्धविराम की आवश्यकता नहीं होती है।

उदाहरण के लिए:

for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")

दोनों अलर्ट दिखाए गए हैं।

इसलिए, हम देख सकते हैं कि अर्धविराम के बिना एक खाली ब्लॉक स्टेटमेंट वैध है और बस कुछ नहीं करता है। इस तरह, जब आप {}[true]डेवलपर टूल (या फायरबग) कंसोल में प्रवेश करते हैं, तो मूल्यांकन किया गया मूल्य अंतिम अभिव्यक्ति कथन का मूल्य होगा । इस मामले में, अंतिम अभिव्यक्ति कथन है [true]

2) असाइनमेंट के संदर्भ में, पार्सर यह सुनिश्चित करेगा कि {}एक वस्तु शाब्दिक है। जब आप var a = करते हैं {}[true], तो आप किसी भी अस्पष्टता को दूर करते हैं और पार्सर को टिप देते हैं जो कि {}ब्लॉक स्टेटमेंट नहीं है।
तो, यहाँ, आप "true"एक खाली वस्तु से एक कुंजी के साथ एक मूल्य प्राप्त करने की कोशिश कर रहे हैं । जाहिर है, इस कुंजी नाम के साथ कोई कुंजी-मूल्य जोड़ी नहीं है। इस तरह, एक चर अपरिभाषित है।

ऑब्जेक्ट कुंजी के रूप में आरक्षित शब्द

ECMAScript 5 ऑब्जेक्ट कुंजियों को आरक्षित शब्द बनाने की अनुमति देता है। तो, निम्नलिखित कुंजियाँ कानूनी हैं:

var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}

3) उदाहरण 1 का एक ही स्पष्टीकरण । लेकिन ... यदि { b: 12345 }भाग को ब्लॉक स्टेटमेंट माना जाता है, तो स्टेटमेंट का प्रकार क्या है b: 12345??

... (?????)

यह एक लेबल स्टेटमेंट है , आप इसे पहले ही देख चुके हैं ... इसका उपयोग लूप और इन में किया जाता है switch। यहां लेबल स्टेटमेंट के बारे में कुछ दिलचस्प लिंक दिए गए हैं: 1 , (2) [ जावास्क्रिप्ट में नेस्टेड लूप्स से तोड़ने का सबसे अच्छा तरीका है? , (3) [ जावास्क्रिप्ट में नेस्टेड छोरों को कैसे तोड़ें?

नोट: बस इसका मूल्यांकन करने का प्रयास करें:

{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :

लेबल के बयान अल्पविराम ऑपरेटर द्वारा अलग नहीं किए जा सकते हैं , आपको उन्हें अर्धविराम के साथ अलग करना होगा। तो यह मान्य है:{a: 1; b: 2}

4) उदाहरण 1 और 3 के स्पष्टीकरण देखें ...

5) एक बार, हमारे पास एक { b: 12345 }कोड ब्लॉक के रूप में माना जा रहा है, और आप डॉट नोटेशन का उपयोग करके कोड ब्लॉक की एक संपत्ति तक पहुंचने की कोशिश कर रहे हैं , और जाहिर है, यह अनुमति नहीं है, और पार्सर एक "Unexpected token :"अपवाद फेंकता है।

6) कोड उपरोक्त उदाहरण के लगभग समान है, लेकिन अभिव्यक्ति समूहीकरण ऑपरेटर के{ b: 12345 } साथ बयान के आसपास से , पार्सर को पता चल जाएगा कि एक वस्तु है। इस तरह, आप संपत्ति को सामान्य रूप से एक्सेस कर पाएंगे ।"b"

7) उदाहरण 2 को याद रखें , हमारे यहां एक असाइनमेंट है, पार्सर जानता है कि { b: 12345 }एक वस्तु है।

8) उपरोक्त उदाहरण की पहचान, लेकिन डॉट नोटेशन के बजाय, यहाँ हम ब्रैकेट नोटेशन का उपयोग कर रहे हैं ।

9) मैंने पहले ही कहा था कि "identifier: value"एक ब्लॉक स्टेटमेंट के अंदर यह सिंटैक्स एक लेबल है। लेकिन, आपको यह भी जानना होगा कि एक लेबल नाम आरक्षित कीवर्ड (ऑब्जेक्ट प्रॉपर्टी के नाम के विपरीत) नहीं हो सकता है। जब हमने एक लेबल को परिभाषित करने का प्रयास किया "true", तो हमें एक मिला SyntaxError

10) फिर, हम एक वस्तु के साथ काम कर रहे हैं। यहां आरक्षित शब्दों का उपयोग करने में कोई समस्या नहीं है। =)

11) अंत में, हमारे पास यह है:!{}[true]

आइए यहां चीजों को अलग करें:

एक) एक निषेध करने से, हम पार्सर को बताए रहे हैं कि {}है एक वस्तु

b) जैसा कि उदाहरण 2 में दिखाया गया है , एक {}वस्तु में एक संपत्ति नहीं है जिसे कहा जाता है true, इसलिए यह अभिव्यक्ति का मूल्यांकन करेगा undefined

ग) अंतिम परिणाम undefinedमूल्य की उपेक्षा है । Javascript इम्प्लिसिटी टाइप undefinedकन्वर्सेशन करता है , और वैल्यू मिथ्या है

d) तो, की उपेक्षा falseहै ... true!

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