2010-03-30 10 views
21

जावास्क्रिप्ट में, एक अंडाकार संख्या स्ट्रिंग दशमलव संख्या के रूप में क्यों डाली जाती है? मैं Number() या + का उपयोग कर हेक्स शाब्दिक स्ट्रिंग कास्ट कर सकता हूं, क्यों अष्टक नहीं?एक स्ट्रिंग के रूप में एक ऑक्टल शाब्दिक क्यों नहीं है?

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

1000 === +"1000" // -> true 
0xFF === +"0xFF" // -> true 
0100 === +"0100" // -> false - +"0100" gives 100, not 64 

मैं जानता हूँ कि मैं parseInt("0100" [, 8]) साथ पार्स कर सकते हैं, लेकिन मुझे पता है कि जैसे कि यह हेक्स और दिसं संख्या के साथ करता है क्यों कास्टिंग काम नहीं करता चाहते हैं।

इसके अलावा, क्या किसी को पता है कि क्यों सख्त मोड में ईसीएमएस्क्रिप्ट 5 वें संस्करण से ऑक्टल अक्षरों को गिरा दिया जाता है?

उत्तर

22

मुझे प्रश्न के लिए थोड़ा देर हो चुकी है लेकिन मुझे लगता है कि मैं एक अच्छा जवाब दे सकता हूं।

स्वीकार किए जाते हैं जवाब आप अधिक है कि आप वास्तव में क्या पता कुछ नहीं बताता है, और सवाल अपने आप में उल्लेख: +value के रूप में काम करता है लेकिन Number(value)parseInt(value) के रूप में नहीं।

कुंजी पता करने के लिए वहाँ एक अर्थ अंतरके बीच जैसे रूपांतरण और पार्स करने है।

एक ऑक्टल संख्या स्ट्रिंग दशमलव संख्या के रूप में क्यों डाली जाती है?

क्योंकि Number constructor called as a Function (Number(value)) और Unary + Operator (+value) पर्दे के पीछे ToNumber आंतरिक आपरेशन का उपयोग करें। उन संरचनाओं का उद्देश्य प्रकार रूपांतरण है।

जब ToNumber is applied to the String Type एक विशेष व्याकरण उत्पादन का उपयोग किया जाता है, जिसे StringNumericLiteral कहा जाता है।

यह उत्पादन केवल दशमलव शाब्दिक और हेक्साडेसिमल पूर्णांक शाब्दिक पकड़ कर सकते हैं:

... 

StrNumericLiteral ::: 
    StrDecimalLiteral 
    HexIntegerLiteral 

...

वहाँ भी इस व्याकरण और "सामान्य" NumericLiterals के व्याकरण के बीच अर्थ मतभेद।

एक StringNumericLiteral:

  • पहले किया जा सकता है और/या सफेद स्थान और/या लाइन टर्मिनेटर्स द्वारा पीछा किया।
  • दशमलव में आपके पास 0 अंकों की संख्या हो सकती है। कोई ऑक्टल नहीं!
  • यह दशमलव + या - इसके संकेत को इंगित करने के लिए पहले किया जा सकता है।
  • यह खाली है या केवल सफेद स्थान +0 में परिवर्तित हो गया है।

अब मैं parseInt और parseFloat फ़ंक्शंस के साथ जाऊंगा।

उन कार्यों के प्रयोजन स्पष्ट रूप से , जो शब्दार्थ अलग को जैसे रूपांतरण है, उदाहरण के लिए पार्स करने है:

parseInt("20px");  // 20 
parseInt("10100", 2); // 20 
parseFloat("3.5GB"); // 3.5 
// etc.. 

उल्लेख है कि parseInt के एल्गोरिथ्म ECMAScript 5 वीं में बदल लायक है संस्करण विशिष्टता, यह अब एक अग्रणी शून्य के लिए ऑक्टल के रूप में किसी संख्या के रेडिक्स को व्याख्या नहीं करता है:

parseInt("010"); // 10, ECMAScript 5 behavior 
parseInt("010"); // 8, ECMAScript 3 behavior 

जैसा कि आप देख सकते हैं, जिसने ईएस 3 और ईएस 5 कार्यान्वयन के बीच व्यवहार में incompatibility पेश किया है, और किसी भी संभावित समस्या से बचने के लिए हमेशा रेडिक्स तर्क का उपयोग करने की अनुशंसा की जाती है।

अब अपने दूसरे प्रश्न:

क्यों अष्टाधारी शाब्दिक कठोर मोड में ECMAScript 5 वें संस्करण से बाहर कर दिया जाता है?

वास्तव में, अष्टाधारी शाब्दिक से छुटकारा पाने के इस प्रयास की बात आती है 1999 के बाद अष्टाधारी शाब्दिक प्रस्तुतियों (OctalIntegerLiteral और OctalEscapeSequence) ECMAScript 3rd Edition specification के बाद से NumericLiteral रों के व्याकरण से हटा दिया गया है, वे backwards compatibility के लिए शामिल किया जा सकता है (also in ES5) मानक के पुराने संस्करणों के साथ।

वास्तव में, वे सभी प्रमुख कार्यान्वयन में शामिल हैं, लेकिन तकनीकी रूप से एक ईएस 3 या ईएस 5 अनुपालन कार्यान्वयन उन्हें शामिल नहीं कर सकता है, क्योंकि उन्हें गैर-मानक के रूप में वर्णित किया गया है।

यह पहला कदम था, अब ECMAScript 5 Strict Mode उन्हें पूरी तरह से अस्वीकार करता है।

लेकिन क्यों?

क्योंकि वे एक त्रुटियों की संभावना सुविधा माना जाता था, और वास्तव में, अतीत में वे अनजाने में या कठिन वजह से कीड़े को पकड़ने के लिए - बस parseInt की अंतर्निहित octals की एक ही समस्या के रूप में -।

अब, सख्त मोड के तहत एक ऑक्टल शाब्दिक SyntaxError अपवाद का कारण बनता है - वर्तमान में केवल फ़ायरफ़ॉक्स 4.0 बीटा में ही देखा जा सकता है -।

+1

यह एक अच्छा जवाब है और जो मूल रूप से मैं अपेक्षा करता था उससे ज्यादा। मुझे लगता है कि मैंने spec में 'StringNumericLiteral' को अनदेखा किया, और मुझे निश्चित रूप से नहीं पता था कि सफेद-स्थान की अनुमति थी। यह उन चीजों में से एक है, मुझे हमेशा सफेद अंतरिक्ष की उम्मीद है * नैन *। –

+2

धन्यवाद @ एंडी, हाँ, मैं वास्तव में लोगों को आश्चर्यचकित करता हूं कि उदा। 'isNaN (" \ t \ r \ n ") 'रिटर्न' झूठा';) – CMS

4

क्योंकि आप वास्तव में उचित अर्थ में कास्टिंग नहीं कर रहे हैं (जेएस कास्टिंग नहीं है) - यह सिर्फ जॉगलिंग टाइप है।

जब आपके पास जावास्क्रिप्ट में कोई शाब्दिक है और उस पर एक विधि लागू है, तो आपके लिए दृश्यों के पीछे एक ऑब्जेक्ट बनाया गया है।

"foo".toUpperCase() उदाहरण के लिए, कि मोटे तौर पर इस new String("foo").toUpperCase();

के बाद से तार एक एकल + ऑपरेटर के साथ मूल्यांकन नहीं किया जा सकता है की तरह लग रहे हैं कोड के मूल्यांकन की जगह, जे एस एक नंबर करने के लिए अपने स्ट्रिंग धर्मान्तरित - और यह नहीं करता है parseInt() या parseFloat() आंतरिक रूप से उपयोग नहीं करते - आपने अनुमान लगाया - यह Number() का उपयोग करता है।

तो, जो मूल्य आप देखते हैं वह Number() की वापसी से आप जो देखते हैं, वह ऑक्टेट मानने के लिए प्रतीत नहीं होता है।

+0

धन्यवाद पीटर, मैंने पहले से ही "कास्टिंग" (यूनिट "का उपयोग किया था जब यूनरी" कास्टिंग "(http://stackoverflow.com/ प्रश्न/61088/छुपा-सुविधाओं-जावास्क्रिप्ट/2243631 # 2243631), यह मेरे लिए अजीब लगता है कि 'संख्या()' व्याकरण द्वारा परिभाषित अनुसार किसी भी कठोर संख्यात्मक शाब्दिक को स्वीकार नहीं करेगा। ऐसा लगता है कि यह संख्यात्मक अक्षरों को पार्स करने के लिए पहले से मौजूद दृश्य कोड के पीछे फिर से उपयोग करने के लिए और अधिक समझदार होगा। पीछे की ओर ऑब्जेक्ट सृजन की जानकारी के लिए धन्यवाद, मैंने इसे पहले पढ़ा है और यह मेरे दिमाग को फिसल गया है, जब वे आपके लिए जादुई तरीके से किए जाते हैं तो इन चीजों को भूलना आसान होता है :-) –

+0

यह हमेशा मुझे खराब करता है मेरे उत्तरों में से अस्वीकार्य है क्योंकि एसई सिस्टम आपको यह नहीं बताता कि यह कौन सा था, इसलिए मैंने सोचा कि मैं विनम्र होगा और आपको बताऊंगा कि आपके 15 अंक कहाँ गए थे। सीएमएस ने एक अच्छा जवाब लिखा जिसने कारणों को और विस्तार से समझाया, इसलिए उसका जवाब स्वीकार करना उचित लग रहा था। क्षमा करें, और आपके उत्तर के लिए धन्यवाद :-) –

+0

@ एंडी कोई चिंता नहीं - मैं सहमत हूं - उसके पास बेहतर जवाब है। चीयर्स। –

1

ईएस 5 में ऑक्टल समर्थन को क्यों हटाया गया था, इसका विस्तार करने के लिए, यह ज्यादातर इसलिए है क्योंकि, नौसिखिया या गैर-प्रोग्रामर के लिए, वाक्यविन्यास अप्रत्याशित है। उदाहरण के लिए प्रमुख शून्यों का उपयोग करके संख्याओं की एक श्रृंखला (शायद जोड़ा जा रहा है) को लंबवत रूप से संरेखित करें, उदाहरण के लिए - यदि आपकी संख्या 8 या 9 का उपयोग नहीं करती है, तो वे ऑक्टल के रूप में व्यवहार समाप्त हो जाएंगे। अचानक आपके कोड को खरबूजे में बंद करने के लिए कोई स्पष्ट कारण नहीं है! यही कारण है कि ऑक्टल समर्थन हटा दिया गया था। एक अलग ऑक्टल सिंटैक्स किसी दिन जोड़ा जा सकता है अगर यह ऐसी दुर्भाग्य नहीं बनाता है (मुझे लगता है कि मुझे 0o755 को एक स्ट्रॉमैन विचार के रूप में देखना याद है), लेकिन अब के लिए ऑक्टल बाहर है।

असंगत parseInt के संबंध में पिछले प्रतिक्रियाओं में उल्लेख किया गया परिवर्तन: कोई कार्यान्वयन इस परिवर्तन को नहीं कर पाया है, और मुझे संदेह है कि कोई कार्यान्वयन इसे नहीं करेगा। ईएस 5 ज्यादातर वास्तविकता में आधारित है। इसकी नई विशेषताएं आम तौर पर मौजूदा कोड को तोड़ती नहीं हैं (सिवाय इसके कि पाठ्यक्रम के नए कोड को नई सुविधाओं का उपयोग करने में सावधानी बरतनी चाहिए जो कि उस उपयोग के हिस्से के रूप में मौजूदा कोड को तोड़ना नहीं है) जो नई सुविधाओं का उपयोग करने की कोशिश नहीं करता है। इसकी असंगतताएं ज्यादातर नगण्य भी हैं, या वे अप्रासंगिक हैं क्योंकि असली दुनिया के कार्यान्वयन ने संगतता कारणों के लिए विनिर्देश को अनदेखा कर दिया है। लेकिन सभी असंगतताओं की अच्छी तरह से स्थापना नहीं की गई है: कुछ सामंजस्यपूर्ण से अधिक आकांक्षी हैं। parseInt में परिवर्तन एक महत्वाकांक्षी परिवर्तन का एक उदाहरण है। यह मौजूदा कोड को तोड़ता है जो ऑक्टेटल के रूप में पार्स करने के लिए एक स्पष्ट रेडिक्स के बिना ऑक्टल सिंटैक्स की अपेक्षा करता है।

कुछ ही दिनों Spidermonkey (मोज़िला JavaScript इंजन) की अवधि के लिए parseInt, जब सख्त मोड कोड, उपेक्षा अष्टाधारी से कहा जाता है, और जब सख्त मोड कोड से नहीं कहा अष्टाधारी समर्थन करने के लिए बनाने के लिए एक आधे रास्ते-परिवर्तन को लागू किया। यह ईएस 5 की इच्छा के करीब है, लेकिन यह सख्त मोड में गैर-सख्त कोड को परिवर्तित करने में स्पष्ट बाधा है, यह संभवतः उपयोगकर्ता को भ्रमित कर देगा, और शायद कार्यान्वयन करने वालों के लिए सबसे दिलचस्प बात यह है कि इसका मतलब है कि आप parseInt को लागू नहीं कर पाएंगे जावास्क्रिप्ट में स्वयं (क्योंकि किसी के कॉलिंग फ़ंक्शन की सख्तता की जांच करने के लिए विनिर्देशन में कोई रास्ता नहीं है), जैसा कि भविष्य के समय (हमले की सतह को कम करने, कार्यान्वयन को कम करने, आदि) के लिए वांछनीय हो सकता है। तो हम निर्भरता को कम करते हैं। (मैंने पैच को parseInt कॉलर-आश्रित बनाने के लिए लिखा है, और मैंने पैच की समीक्षा की है ताकि इसे शुरू किया जा सके, मेरे शुरुआती पैच के उतरने के बाद आगे की चर्चा से उत्पन्न हो गया।) parseInt अब ईएस 3 के अनुरूप है, और वेब को दिया गया है, और यह कि ईएस 5 अर्थशास्त्र शायद इसके साथ संगत नहीं हैं, मुझे संदेह है कि हम बदल जाएंगे। इसलिए मुझे संदेह है कि दूसरों को भी बदल जाएगा। (मुझे यह भी यकीन है कि वे parseInt में अंतर्निहित ऑक्टल वाक्यविन्यास की ईएस 5 की महत्वाकांक्षी निषेध के साथ वेब की असंगतता की डिग्री के हमारे आकलन के साथ सहमत होंगे, और शायद हमारे अन्य कारणों से भी। अगर हम बदलना चाहते हैं तो भी मैं हूं यकीन नहीं है कि वे अनुसरण करेंगे, और मुझे संदेह है कि वे स्मार्ट नहीं होंगे।)

+0

+1, अतिरिक्त अंतर्दृष्टि के लिए धन्यवाद।मैं मानता हूं, ऑक्टल अक्षरों के लिए व्याकरण अनजान के लिए खतरनाक है, हेक्स शाब्दिक व्याकरण के '0x' उपसर्ग के विपरीत जो इसे दशमलव अक्षर से बाहर खड़ा करता है। –