2010-01-20 14 views
11

उत्पन्न करता है मुझे JavaScript के आंतरिक को समझने में रूचि है। मैंने SpiderMonkey और Rhino के लिए स्रोत पढ़ने की कोशिश की है, लेकिन मेरे सिर को चारों ओर लपेटना काफी जटिल है।क्यों (! [] + []) [+ !! [] + []] "ए"

कारण मैं पूछ रहा है: क्यों

  • (![]+[])[+!![]+[]] उपज की तरह कुछ "a"
  • (Å=[],[µ=!Å+Å][µ[È=++Å+Å+Å]+({}+Å)[Ç=!!Å+µ,ª=Ç[Å]+Ç[+!Å],Å]+ª])()[µ[Å]+µ[Å+Å]+Ç[È]+ª](Å)alert(1) उत्पादन करता है?

स्रोत: http://sla.ckers.org/forum/read.php?24,32930,page=1

उस मंच पर जावास्क्रिप्ट विषमता के कई और उदाहरण हैं और मैं जानना चाहता हूं कि वेब अनुप्रयोग सुरक्षा के संबंध में प्रोग्रामिंग दृष्टिकोण से यह कैसे काम करता है।

+0

यदि आप रुचि रखते हैं कि भाषाएं कैसे काम करती हैं, तो इसके लिए एक कंपाइलर लिखना कुछ भी नहीं है - जो मूल रूप से आपको भाषा और इसके आंतरिक सिखाएंगे। – Chii

+0

सभी प्रतिक्रियाओं के लिए धन्यवाद। मुझे पता था कि जावास्क्रिप्ट ने कुछ जादू किया है लेकिन कुछ चीजें जो खतरनाक हैं वह खतरनाक है ... – prafulfillment

उत्तर

12

क्यों (![]+[])[+!![]+[]] उत्पादन "एक" कदम से

कदम नहीं करता है। प्रथम बिट पहले से ही artemb द्वारा समझाया गया था: [] एक सरणी है। इसे नकारात्मक, ![] एक बूलियन, false का मूल्यांकन करता है - यह ! काम करता है जब यह null या अपरिभाषित किसी चीज़ पर लागू होता है। फिर से artemb द्वारा इंगित, इस +[] संलग्न करने से बूलियन को एक स्ट्रिंग में परिवर्तित करने के लिए मजबूर करता है। ऐसा इसलिए है क्योंकि + एक स्ट्रिंग कॉन्सटेनेशन ऑपरेटर है। बूलियन false को इसके स्ट्रिंग प्रस्तुति में परिवर्तित किया जाता है, "false"

फिर, दूसरा बिट, [+!![]+[]]। सबसे पहले, बाहरी [ और ] पिछली स्ट्रिंग का इलाज करने के लिए काम करता है, जिसे हम अभी डिवाइव किया गया है, वर्णों की एक सरणी के रूप में "false" के बराबर है। [ और ] के अंदर एक पूर्णांक अनुक्रमणिका डालने से, आप एक विशेष अनुक्रमणिका में चरित्र प्राप्त करते हैं। तो क्या रहता है +!![]+[] इसमें 4 टुकड़े होते हैं: +, !![], + और []। पहले !![] का मूल्यांकन किया गया है।हमने पहले ही देखा है कि ![] एक बूलियन false है इसलिए ! को पूर्ववत करना इसे अस्वीकार करता है, और true उत्पन्न करता है। अगली बात क्या होता है कि +!![] में + लागू किया जाता है, और + लगाने से यह संख्या प्रतिनिधित्व है, जो है 1 (ताकि +true है 1) +[] इस प्रकार है कि एक स्ट्रिंग फिर से कि 1"1" उपज लेकिन बनाता में बूलियन true धर्मान्तरित यह वास्तव में समझ में नहीं आता है, छोटी अभिव्यक्ति (![]+[])[+!![]] पहले से ही a उत्पन्न करती है। +[] को जोड़ना या तो चोट नहीं पहुंचाता है, परिणामी अभिव्यक्ति [1] के बजाय ["1"] है। मेरा झटका यह है कि जब [] किसी सरणी पर लागू होता है, जो [] के अंदर जो भी हो, उसे एक संख्या में घुमाया जाएगा, जो "1" के लिए 1 फिर से देगा। तो या तो रास्ता, +!![]+[]1 का मूल्यांकन करता है, अंतिम अभिव्यक्ति: "false"[1] जो कह रहा है: स्ट्रिंग "false" से इंडेक्स 1 पर वर्ण को चित्रित करें, और डिफ़ॉल्ट रूप से, सरणी जावास्क्रिप्ट में 0 से शुरू होती है, यह "false" का दूसरा अक्षर है, और a

16

यदि आप समझना चाहते हैं कि वे डरावनी अभिव्यक्तियां क्यों काम करती हैं, तो आप फ़ायरबग कंसोल खोल सकते हैं और स्वयं का प्रयोग कर सकते हैं। मैंने किया और मुझे लगता है कि ![]false है, !![]true है, जो एक बूलियन मान (false+[] या true+[]) में एक सरणी जोड़कर इस मान का एक स्ट्रिंग-संस्करण उत्पन्न करता है (false+[]="false")।

इस तरह अभिव्यक्ति करने पर निर्भर करता:

"false"["1"] 

जो स्पष्ट रूप से है "एक"

+4

यह स्पष्ट कैसे है? – medopal

+0

यह इस अर्थ में स्पष्ट है कि, यदि आपके हाथों पर पर्याप्त समय है, और कुछ रचनात्मकता है तो आप स्ट्रिंग कॉन्सटेनेशन और इंडेक्स एक्सेसर्स के इस सीमित सेट का उपयोग मनमाने ढंग से तार बनाने के लिए कर सकते हैं। –

+0

@medopal शायद पूरी तरह से स्पष्ट नहीं है :) यह स्ट्रिंग "झूठी" ('एफ' = 0, 'ए' = 1, 'एल' = 2, 'एस' = 3 में "ए" अक्षर की अनुक्रमणिका है , 'ई' = 4)। –

1

मैं तुम्हें प्राप्त करने और पढ़ने के लिए सलाह देते हैं:

  • ECMAScript मानक (ECMA 262), 5 वीं संस्करण
  • एडोब दस्तावेज़ "एवीएम 2 सिंहावलोकन" कहा जाता है जो एवीएम 2 आभासी मशीन की वास्तुकला बताता है, जिस पर एडोब फ्लैश और इसकी एक्शनस्क्रिप्ट चलाते हैं। (![]+[]) और [+!![]+[]]: इस में पार्स किया गया है:
2

क्यों [+ !! [] []] का उत्पादन "एक"

  1. !expr ([] []!) - expr पर ToBoolean कॉल करता है और बूलियन मान flips। दूसरे शब्दों में, एक खाली सरणी जैसे सच्चे मान ऑपरेटर के साथ उपयोग किए जाने पर झूठी उत्पन्न करेंगे।
  2. a + b - दोनों अभिव्यक्तियों को आंतरिक ToPrimitive के माध्यम से चलाया जाता है। यदि कोई परिणामस्वरूप मान एक स्ट्रिंग है, तो स्ट्रिंग कॉन्सटेनेशन किया जाता है। अन्यथा primitives ToNumber के माध्यम से चलाया जाता है और जोड़ा। वस्तुओं के लिए अनुवांशिक (सरणी शामिल) करने के लिए स्ट्रिंग और मूल्य का प्रयास करेंगे। Array.prototype.toString किसी पैरामीटर के साथ कॉलिंग कॉलिंग के रूप में कार्य करता है। इस प्रकार, ![] + [] = false + "" = "false"
  3. !![] == true, यूनरी प्लस ऑपरेटर अभिव्यक्ति को एक संख्या में परिवर्तित करता है, इसलिए 1। फिर, सरणी को "" में परिवर्तित किया गया है ताकि +!![]+[] == "1" हो।
  4. अभिव्यक्ति ("false")["1"] == "a"

अन्य अभिव्यक्ति इसी तरह से नीचे उबला हुआ जा सकता है निर्भर करता है। यह यूनिकोड स्ट्रिंग्स को गड़बड़ करने के लिए उपयोग करता है और यह लंबा है, लेकिन सीधे "पार्स" के लिए आगे की तरह।

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