इस कोड में संख्या वस्तुओं के गुण रखने और संख्या बढ़ाने के साथ क्या हो रहा है?


246

हाल ही में किए गए एक ट्वीट में जावास्क्रिप्ट का यह अंश शामिल था।

क्या कोई कृपया बता सकता है कि इसमें कदम-कदम पर क्या हो रहा है?

> function dis() { return this }
undefined
> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}
> five.wtf = 'potato'
"potato"
> five.wtf
"potato"
> five * 5
25
> five.wtf
"potato"
> five++
5
> five.wtf
undefined
> five.wtf = 'potato?'
"potato?"
> five.wtf
undefined
> five
6

विशेष रूप से, यह मेरे लिए स्पष्ट नहीं है:

  • क्यों का परिणाम dis.call(5)एक है Numberएक किसी तरह का साथ [[PrimitiveValue]]संपत्ति है, लेकिन के परिणामों five++और five * 5सिर्फ सादा संख्या होना दिखाई 5और 25(नहीं Numberहै)
  • वेतन वृद्धि के five.wtfबाद संपत्ति क्यों गायब हो जाती हैfive++
  • क्यों five.wtfसंपत्ति में five++वृद्धि के बाद भी संपत्ति नहीं रह जाती है , five.wtf = 'potato?'काम के बावजूद, जाहिर तौर पर मूल्य निर्धारित करने के बावजूद ।

6
हाहा मैंने वो ट्वीट देखा !! यह इतना विचित्र है, मुझे लगता है कि क्योंकि आप इसे गुणा करते हैं, यह वस्तु को काफी प्रभावित नहीं करता है, लेकिन ++अंतर्निहित प्रकार को प्रभावित करने के लिए लगता है
कैलम लिन्गिंगटन

8
आपको कौन सी लाइन समझ में नहीं आई? Preबनाम Postवेतन वृद्धि? गुणन के बाद, यह फिर से एक ऐसी Numberवस्तु है, जिसमें wtfसंपत्ति नहीं है ... लेकिन फिर भी यह एक ऐसा है जो objectहो सकता है properties..
रेयन

25
जब आप कॉल disकरते हैं dis.call(5), तो यह आदिम संख्या 5को Numberउस प्रकार की वस्तु में लपेटता है जिसमें यह होता है 5, ताकि यह ऑब्जेक्ट ऑब्जेक्ट के रूप में वापस आ सके this++धर्मान्तरित यह एक आदिम संख्या कि गुण नहीं हो सकते करने के लिए वापस, तो wtfअपरिभाषित जा करने के लिए शुरू होता है।
जीसर्ज जूल


5
@ रेयान ... और वह ES6 के साथ बदल गया है । इसलिए आगे जाकर यह पूरी घटना घटनी बंद हो जाएगी।
जीसर्ज जूल

जवाबों:


278

यहां ओ.पी. स्टैक ओवरफ्लो पर इसे देखने के लिए मजेदार :)

व्यवहार के माध्यम से कदम रखने से पहले, कुछ बातों को स्पष्ट करना महत्वपूर्ण है:

  1. संख्या मान और संख्या ऑब्जेक्ट ( a = 3बनाम a = new Number(3)) बहुत अलग हैं। एक आदिम है, दूसरी वस्तु है। आप प्राथमिकताओं को विशेषता प्रदान नहीं कर सकते, लेकिन आप वस्तुओं को कर सकते हैं

  2. दोनों के बीच जबरदस्ती निहित है।

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

    (new Number(3) === 3)  // returns false
    (new Number(3) == 3)   // returns true, as the '==' operator coerces
    (+new Number(3) === 3) // returns true, as the '+' operator coerces
  3. हर एक्सप्रेशन का रिटर्न वैल्यू होता है। जब REPL एक अभिव्यक्ति को पढ़ता है और निष्पादित करता है, तो यह वही प्रदर्शित करता है। वापसी मूल्यों का मतलब अक्सर यह नहीं होता है कि आप क्या सोचते हैं और उन चीजों को लागू करते हैं जो अभी सच नहीं हैं।

ठीक है चले हम।

जावास्क्रिप्ट कोड की मूल छवि

शपथ।

> function dis() { return this }
undefined
> five = dis.call(5)
[Number: 5]

एक फ़ंक्शन को परिभाषित करें disऔर इसे कॉल करें5 । यह फ़ंक्शन 5को संदर्भ ( this) के रूप में निष्पादित करेगा । यहां इसे संख्या मान से संख्या ऑब्जेक्ट तक ले जाया जाता है। यह नोट करना बहुत महत्वपूर्ण है कि हम सख्त मोड में थे ऐसा नहीं हुआ होगा

> five.wtf = 'potato'
'potato'
> five.wtf
'potato'

अब हम विशेषता five.wtfको 'potato'पांच के साथ सेट करते हैं , और एक वस्तु के रूप में पांच के साथ, निश्चित रूप से यह साधारण असाइनमेंट को स्वीकार करता है ।

> five * 5
25
> five.wtf
'potato'

साथ fiveएक वस्तु के रूप में, मैं यह अभी भी सरल अंकगणितीय आपरेशनों प्रदर्शन कर सकते हैं सुनिश्चित करते हैं। यह। क्या इसकी विशेषताएं अभी भी छड़ी हैं? हाँ।

मोड़।

> five++
5
> five.wtf
undefined

अब हम जाँच करते हैं five++उपसर्ग वृद्धि के साथ चाल यह है कि संपूर्ण अभिव्यक्ति मूल मूल्य के खिलाफ मूल्यांकन करेगी और फिर मूल्य वृद्धि करेगी । ऐसा लगता है fiveकि अभी भी पांच हैं, लेकिन वास्तव में अभिव्यक्ति का मूल्यांकन पांच में किया गया, फिर सेट किया fiveगया 6

न केवल fiveकरने के लिए तैयार है 6, लेकिन यह वापस एक संख्या मान में coerced किया गया था, और सभी गुण खो जाते हैं। चूँकि आदिम विशेषताओं को नहीं पकड़ सकते हैं, five.wtfअपरिभाषित है।

> five.wtf = 'potato?'
'potato?'
> five.wtf
undefined

मैं फिर से एक विशेषता wtfको पुन: सौंपने का प्रयास करता हूं five। रिटर्न वैल्यू का मतलब यह चिपक जाता है, लेकिन यह वास्तव में नहीं है क्योंकि fiveएक नंबर वैल्यू है, न कि एक नंबर ऑब्जेक्ट। अभिव्यक्ति का मूल्यांकन होता है 'potato?', लेकिन जब हम जांचते हैं तो हम देखते हैं कि इसे असाइन नहीं किया गया था।

प्रतिष्ठा।

> five
6

जब से पोस्टफिक्स इन्क्रीमेंट हुआ है, fiveतब से 6


70
क्या आप बारीकी से देख रहे हैं?
वडडल्स

3
@ नातान लांग वेल, जावा में, जिसे जावास्क्रिप्ट ने शुरुआत से ही भारी मात्रा में उधार लिया था, सभी प्राइमेटिव के पास एक वर्ग बराबर है। intऔर Integer, उदाहरण के लिए। मुझे लगता है कि यह ऐसा है जिससे आप एक फ़ंक्शन बना सकते हैं doSomething(Object), और फिर भी इसे प्रिमिटिव देने में सक्षम हो सकते हैं। इस मामले में प्रिमिटिव्स को उनकी संबंधित कक्षाओं में परिवर्तित किया जाएगा। लेकिन जेएस वास्तव में प्रकारों के बारे में परवाह नहीं करता है, इसलिए कारण शायद कुछ और है
जूल

4
@ एरिक पहली बात ++मूल्य के लिए ToNumber लागू है । तार के साथ एक समान मामले की तुलना करें: यदि आपके पास है x="5", तो x++संख्या लौटाता है 5
अप्सिलर्स

2
वास्तव में जादू सब पर होता है dis.call(5), आपत्ति करने के लिए जबरदस्ती, मैंने कभी भी उम्मीद नहीं की होगी।
mcfedr

3
@ इसके अलावा इसके कई और अधिक विस्तृत प्रभाव हैं, जिसमें इसके मानक पुस्तकालय के बड़े हिस्से का नामकरण, मानक वस्तु प्रकारों का व्यवहार और यहां तक ​​कि तथ्य यह है कि यह एक ब्रेस-एंड-सेमीकोलन सिंटैक्स का उपयोग करता है (भले ही अर्धविराम हों वैकल्पिक) इस तथ्य से प्राप्त होता है कि इसे जावा प्रोग्रामर से परिचित होने के लिए डिज़ाइन किया गया था। हां, यह शुरुआती लोगों को भ्रमित कर रहा है। इसका मतलब यह नहीं है कि प्रभाव मौजूद नहीं है।
जूल्स

77

किसी संख्या को दर्शाने के दो अलग-अलग तरीके हैं:

var a = 5;
var b = new Number(5);

पहला एक आदिम है, दूसरा एक वस्तु है। सभी इरादों और उद्देश्यों के लिए दोनों समान व्यवहार करते हैं, सिवाय इसके कि वे कंसोल पर मुद्रित होने पर अलग दिखते हैं। एक महत्वपूर्ण अंतर यह है कि, एक वस्तु के रूप में, new Number(5)किसी भी सादे की तरह नए गुणों को स्वीकार करता है {}, जबकि आदिम 5नहीं है:

a.foo = 'bar';  // doesn't stick
b.foo = 'bar';  // sticks

प्रारंभिक dis.call(5)भाग के लिए, कृपया देखें कि "यह" कीवर्ड कैसे काम करता है? । मान लें कि पहले तर्क callका उपयोग मूल्य के रूप में किया जाता है this, और यह ऑपरेशन संख्या को और अधिक जटिल Numberऑब्जेक्ट रूप में बाध्य करता है। * बाद में ++इसे वापस आदिम रूप में बाध्य करता है, क्योंकि अतिरिक्त संचालन के +परिणामस्वरूप एक नया आदिम होता है।

> five = dis.call(5)  // for all intents and purposes same as new Number(5)
Number {[[PrimitiveValue]]: 5}
> five.wtf = 'potato'
"potato"
> five.wtf
"potato"

एक Numberवस्तु नए गुणों को स्वीकार करती है।

> five++

++एक नए आदिम 6मूल्य के परिणाम ...

> five.wtf
undefined
> five.wtf = 'potato?'
"potato?"
> five.wtf
undefined

... जो नहीं है और कस्टम विशेषताओं को स्वीकार नहीं करता है।

* ध्यान दें कि सख्त मोड में thisतर्क को अलग तरह से माना जाएगा और इसे एक में परिवर्तित नहीं किया जाएगा Number। देखें http://es5.github.io/#x10.4.3 कार्यान्वयन विवरण के लिए।


2
@ Cha / C ++ में बेहतर तरीके से सुनिश्चित करें कि आप कहां कर सकते हैं #define true false। या जावा में, जहां आप सिर्फ संख्या को फिर से परिभाषित कर सकते हैं। ये अच्छी ठोस भाषाएं हैं। सही मायने में, हर भाषा में समान "ट्रिक्स" होती हैं, जहाँ आपको एक परिणाम मिलता है जो उद्देश्य के अनुसार काम करता है, लेकिन अजीब लग सकता है।
१०:

1
@ वेल्ड ओके ने मुझे इस बात की पुष्टि कर दी कि, यह है कि मुझे बतख टाइपिंग से नफरत है।
फराप

59

जावास्क्रिप्ट वर्ल्ड में जबरदस्ती है - एक जासूसी कहानी

नाथन, आपको पता नहीं है कि आपने क्या उजागर किया है।

मैं अब हफ्तों से इसकी जांच कर रहा हूं। यह सब पिछले अक्टूबर की तूफानी रात में शुरू हुआ। मैं गलती से Numberकक्षा में लड़खड़ा गया - मेरा मतलब है, दुनिया में जावास्क्रिप्ट जावास्क्रिप्ट क्यों थाNumber वर्ग क्यों है?

मैं इसके लिए तैयार नहीं था कि मैं आगे क्या पता लगाने जा रहा हूं।

यह पता चलता है कि जावास्क्रिप्ट, आपको बताए बिना, आपके नंबरों को वस्तुओं और आपकी वस्तुओं को आपकी नाक के नीचे नंबरों में बदल रहा है।

जावास्क्रिप्ट उम्मीद कर रहा था कि कोई भी पकड़ नहीं पाएगा, लेकिन लोग अजीब अप्रत्याशित व्यवहार की रिपोर्ट कर रहे हैं, और अब आपके और आपके प्रश्न के लिए मेरे पास सबूत हैं कि मुझे इस बात को व्यापक रूप से खोलने की जरूरत है।

यह वही है जो हमने अब तक पाया है। मुझे नहीं पता कि क्या मुझे भी आपको यह बताना चाहिए - आप अपने जावास्क्रिप्ट को बंद करना चाह सकते हैं।

> function dis() { return this }
undefined

जब आपने वह फ़ंक्शन बनाया, तो आपको शायद पता नहीं था कि आगे क्या होने वाला है। सब कुछ ठीक लग रहा था, और सब कुछ ठीक था - अभी के लिए।

कोई त्रुटि संदेश, बस कंसोल आउटपुट में "अपरिभाषित" शब्द, वास्तव में आप क्या उम्मीद करेंगे। आखिरकार, यह एक फ़ंक्शन घोषणा थी - इसे कुछ भी वापस करने के लिए नहीं माना जाता है।

लेकिन यह सिर्फ शुरुआत थी। आगे क्या हुआ, कोई भी भविष्यवाणी नहीं कर सकता था।

> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}

हाँ, मुझे पता है, तुम एक की उम्मीद है 5, लेकिन वह नहीं है जो आपको मिला, वह था - आपको कुछ और मिला - कुछ अलग।

मेरे साथ भी ठीक वैसा ही हुआ था।

मुझे नहीं पता था कि इसका क्या बनाना है। इसने मुझे पागल कर दिया। मैं सो नहीं सका, मैं नहीं खा सकता था, मैंने इसे पीने की कोशिश की, लेकिन माउंटेन ड्यू की कोई भी मात्रा मुझे भूल नहीं पाएगी। यह सिर्फ कोई मतलब नहीं था!

जब मुझे पता चला कि वास्तव में क्या चल रहा था - यह जबरदस्ती थी, और यह मेरी आंखों के सामने वहीं हो रहा था, लेकिन मैं इसे देखने के लिए बहुत अंधा था।

मोज़िला ने इसे डालकर दफनाने की कोशिश की जहां उन्हें पता था कि कोई भी नहीं देखेगा - उनके दस्तावेज

पुन: पढ़ने और फिर से पढ़ने और फिर से पढ़ने के घंटों के बाद मुझे यह मिला:

"... और आदिम मूल्य वस्तुओं में परिवर्तित हो जाएंगे।"

यह वहीं था जैसा कि ओपन सेन्स फॉन्ट में लिखा जा सकता है। यह call()समारोह था - मैं इतना मूर्ख कैसे हो सकता है ?!

मेरा नंबर अब एक नंबर नहीं था। जिस क्षण मैंने इसे पारित किया call(), यह कुछ और हो गया। यह बन गया ... एक वस्तु।

मैं यह पहली बार में विश्वास नहीं कर सकता। यह सच कैसे हो सकता है? लेकिन मैं उन सबूतों को नजरअंदाज नहीं कर सकता जो मेरे आसपास बढ़ रहे थे। यह ठीक है अगर तुम सिर्फ देखो:

> five.wtf = 'potato'
"potato"

> five.wtf
"potato"

wtfसही था। संख्याओं में कस्टम गुण नहीं हो सकते हैं - हम सभी जानते हैं कि! यह पहली बात है कि वे आपको अकादमी में पढ़ाते हैं।

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

यह था ... new Number(5)

बेशक! यह सही समझ में आया। call()एक काम करना था, उसे एक समारोह में शामिल होना था, और यह करने के लिए कि उसे आबाद करने की आवश्यकता है this, वह जानता था कि वह ऐसा नहीं कर सकता है - उसे एक वस्तु की आवश्यकता थी और वह इसे प्राप्त करने के लिए कुछ भी करने को तैयार था, यहां तक ​​कि अगर इसका मतलब हमारे नंबर के साथ ज़बरदस्ती करना है। जब call()नंबर देखा 5, वह एक अवसर देखा।

यह एकदम सही योजना थी: तब तक प्रतीक्षा करें जब तक कोई नहीं देख रहा था और हमारे नंबर को एक वस्तु के लिए स्वैप कर रहा था जो इसे जैसा दिखता है। हम एक नंबर प्राप्त करते हैं, फ़ंक्शन को आमंत्रित किया जाता है, और कोई भी समझदार नहीं होगा।

यह वास्तव में सही योजना थी, लेकिन सभी योजनाओं की तरह, यहां तक ​​कि पूर्ण वाले भी, इसमें एक छेद था, और हम इसे सही तरीके से गिराने वाले थे।

देखिए, जो call()समझ में नहीं आया वह यह था कि वह शहर में एकमात्र ऐसा व्यक्ति नहीं था, जो संख्याओं में सामंजस्य स्थापित कर सकता था। यह सब के बाद जावास्क्रिप्ट था - हर जगह जबरदस्ती थी।

call() मेरा नंबर लिया, और मैं तब तक रुकने वाला नहीं था जब तक कि मैं उसके छोटे से नकाब से नकाब हटाकर उसे पूरे स्टैक ओवरफ्लो समुदाय में उजागर नहीं कर देता।

पर कैसे? मुझे एक योजना की जरूरत थी। यकीन है कि यह एक संख्या की तरह दिखता है, लेकिन मुझे पता है कि यह नहीं है, यह साबित करने का एक तरीका होगा। बस! यह संख्या की तरह दिखता है , लेकिन क्या यह एक जैसा काम कर सकता है?

मैंने बताया कि fiveमुझे उससे 5 गुना बड़ा बनने की जरूरत है - उसने पूछा क्यों नहीं और मैंने समझाया नहीं। मैंने तब कोई भी अच्छा प्रोग्रामर किया था: मैंने कई गुना किया। निश्चित रूप से ऐसा कोई तरीका नहीं था जिससे वह अपना रास्ता नकली कर सके।

> five * 5
25
> five.wtf
'potato'

लानत है! इतना ही नहीं अभी भी fiveसिर्फ ठीक wtfथा। लानत है इस लड़के और उसके आलू से।

आखिर क्या चल रहा था? क्या मैं इस पूरी बात के बारे में गलत था? क्या fiveवास्तव में एक संख्या है? नहीं, मुझे कुछ याद आ रहा है, मैं इसे जानता हूं, कुछ ऐसा है जिसे मैं भूल रहा हूं, कुछ इतना सरल और बुनियादी है कि मैं इसे पूरी तरह से देख रहा हूं।

यह अच्छा नहीं लग रहा था, मैं यह जवाब घंटों से लिख रहा था और मैं अभी भी अपनी बात बनाने के करीब नहीं था। मैं इसे जारी नहीं रख सका, अंततः लोग पढ़ना बंद कर देंगे, मुझे कुछ सोचना था और मुझे इसके बारे में तेजी से सोचना था।

रुको कि यह है! five25, 25 परिणाम नहीं था, 25 एक पूरी तरह से अलग संख्या थी। बेशक, मैं कैसे भूल सकता था? नंबर अपरिवर्तनीय हैं। जब आप गुणा करते हैं तो आपको 5 * 5कुछ भी नहीं सौंपा जाता है जिससे आप एक नया नंबर बनाते हैं 25

यही होना चाहिए। किसी तरह जब मैं गुणा करता हूं five * 5, तो fiveसंख्या में तालमेल होना चाहिए और उस संख्या को गुणन के लिए उपयोग किया जाना चाहिए। यह उस गुणन का परिणाम है जो कंसोल पर मुद्रित होता है, fiveस्वयं के मूल्य पर नहीं । fiveकभी भी कुछ भी नहीं सौंपा जाता है - इसलिए निश्चित रूप से यह नहीं बदलता है।

तो फिर मैं अपने आप fiveको एक ऑपरेशन का परिणाम कैसे दे सकता हूं । मैं समझ गया। इससे पहले fiveकि सोचने का मौका मिले, मैंने "++" चिल्लाया।

> five++
5

अहा! मैं उसके पास था! हर कोई जानता 5 + 1है 6, यह एक सबूत था जो मुझे उजागर करने की आवश्यकता fiveथी जो एक संख्या नहीं थी! यह एक पाखण्डी था! एक बुरा नपुंसक जो गिनती करना नहीं जानता था। और मैं इसे साबित कर सकता था। यहां बताया गया है कि वास्तविक संख्या कैसे कार्य करती है:

> num = 5
5
> num++
5

रुको? यहां पर क्या हो रहा था? उच्छ्वास में मैं इतना फंस गया fiveकि मैं भूल गया कि पोस्ट ऑपरेटर कैसे काम करते हैं। जब मैं का उपयोग ++अंत में की fiveमैं वापसी कह रहा हूँ वर्तमान मान, तो बढ़ा देते five। ऑपरेशन से पहले वह मूल्य होता है जो कंसोल पर प्रिंट हो जाता है। numवास्तव में था 6और मैं इसे साबित कर सकता था:

>num
6

यह देखने का समय कि fiveवास्तव में क्या था:

>five
6

... यह वही था जो होना चाहिए। fiveअच्छा था - लेकिन मैं बेहतर था। अगर fiveअभी भी एक वस्तु थी, जिसका मतलब होगा कि इसके पास अभी भी संपत्ति होगी wtfऔर मैं वह सब कुछ शर्त लगाने को तैयार था जो यह नहीं करता था।

> five.wtf
undefined

अहा! मैं सही था। मैं उसके पास था! fiveअब एक संख्या थी - यह अब कोई वस्तु नहीं थी। मुझे पता था कि गुणा चाल इस बार इसे नहीं बचाएगी। देखें five++वास्तव में है five = five + 1। गुणा के विपरीत, ++ऑपरेटर एक मान प्रदान करता है five। अधिक विशेष रूप से, यह उसे परिणाम प्रदान करता है five + 1जैसे कि गुणन के मामले में एक नया अपरिवर्तनीय संख्या देता है

मुझे पता था कि मैं उसके पास था, और सिर्फ यह सुनिश्चित करने के लिए कि वह उसके रास्ते से हट नहीं सकता था। मैं अपनी आस्तीन ऊपर एक और परीक्षण किया था। अगर मैं सही था, और fiveअब वास्तव में एक नंबर था, तो यह काम नहीं करेगा:

> five.wtf = 'potato?'
'potato?'

वह इस बार मुझे बेवकूफ बनाने वाला नहीं था। मुझे पता potato?था कि कंसोल पर प्रिंट होना है क्योंकि यह असाइनमेंट का आउटपुट है। असली सवाल यह wtfहै कि क्या अब भी रहेगा?

> five.wtf
undefined

बस के रूप में मुझे संदेह है - कुछ भी नहीं - क्योंकि संख्या को गुण नहीं सौंपा जा सकता है। हमने सीखा कि अकादमी में पहले वर्ष;)

धन्यवाद नाथन। इस प्रश्न को पूछने में आपके साहस की बदौलत मैं अंत में यह सब मेरे पीछे रख सकता हूं और एक नए मामले की ओर बढ़ सकता हूं।

इस समारोह के बारे में एक तरह toValue()। हे भगवान। Nooo!


9
इसे भूल जाओ जेक; यह जावास्क्रिप्ट है।
सेठ

जेएस में हम निर्माण कार्यों को "कक्षाएं" क्यों कहते हैं?
एवोल्यूशनबक्स

27
01 > function dis() { return this }
02 undefined
03 > five = dis.call(5)
04 Number {[[PrimitiveValue]]: 5}
05 > five.wtf = 'potato'
06 "potato"
07 > five.wtf
08 "potato"
09 > five * 5
10 25
11 > five.wtf
12 "potato"
13 > five++
14 5
15 > five.wtf
16 undefined
17 > five.wtf = 'potato?'
18 "potato?"
19 > five.wtf
20 undefined
21 > five
22 6

01एक फ़ंक्शन घोषित करता है disजो संदर्भ ऑब्जेक्ट को लौटाता है। क्या thisप्रतिनिधित्व करता आप सख्त मोड का उपयोग कर या नहीं कर रहे हैं, इस आधार पर बदल जाता है। पूरे उदाहरण के अलग-अलग परिणाम हैं यदि फ़ंक्शन के रूप में घोषित किया गया था:

> function dis() { "use strict"; return this }

यह ES5 विनिर्देश में अनुभाग 10.4.3 में विस्तृत है

  1. यदि फ़ंक्शन कोड सख्त कोड है, तो ThisBinding को thisArg पर सेट करें।
  2. यदि यह आधार शून्य या अपरिभाषित है, तो इस ऑब्जेक्ट को वैश्विक ऑब्जेक्ट पर सेट करें।
  3. यदि टाइप (thisArg) ऑब्जेक्ट ऑब्जेक्ट नहीं है, तो ToBbject (ThisArg) में यह सेट करें।

02 फ़ंक्शन की वापसी का मूल्य है। undefinedयहाँ आत्म व्याख्यात्मक होना चाहिए।

03जब आदिम मान के संदर्भ में कहा जाता है, तो चर fiveको रिटर्न वैल्यू के साथ आरंभ किया disजाता है 5। क्योंकि disसख्त मोड में नहीं है, यह लाइन कॉलिंग के समान हैfive = Object(5)

04विषम Number {[[PrimitiveValue]]: 5}वापसी मूल्य उस वस्तु का प्रतिनिधित्व है जो आदिम मूल्य को लपेटता है5

05fiveवस्तु की wtfसंपत्ति का एक स्ट्रिंग मान असाइन किया गया है'potato'

06 असाइनमेंट का रिटर्न वैल्यू है और स्व-व्याख्यात्मक होना चाहिए।

07fiveवस्तु हैwtf संपत्ति की जांच की जा रही है

08जैसा five.wtfकि पहले 'potato'यह रिटर्न करने के लिए तैयार था'potato' यहाँ है

09fiveवस्तु आदिम मूल्य से गुणा किया जा रहा है 5। यह किसी भी अन्य ऑब्जेक्ट के गुणन से अलग नहीं है और इसे ES5 विनिर्देश की धारा 11.5 में समझाया गया है । विशेष रूप से ध्यान दें कि वस्तुओं को संख्यात्मक मानों में कैसे डाला जाता है, जो कुछ वर्गों में कवर किया जाता है।

9.3 ToNumber :

  1. PrimValue को ToPrimitive (इनपुट तर्क, संकेत संख्या) होने दें।
  2. ToNumber (primValue) वापस करें।

9.1 ToPrimitive :

ऑब्जेक्ट के लिए एक डिफ़ॉल्ट मान लौटाएं। ऑब्जेक्ट का डिफ़ॉल्ट मान [[DefaultValue]] ऑब्जेक्ट की आंतरिक विधि को कॉल करके प्राप्त किया जाता है, वैकल्पिक संकेत PreferredType से गुजर रहा है। [[DefaultValue]] आंतरिक विधि के व्यवहार को इस विनिर्देश द्वारा परिभाषित किया गया है जो कि M.१२ . 8.1 में सभी देशी ECMAScript ऑब्जेक्ट्स के लिए है ।

8.12.8 [[DefaultValue]] :

मान दें कि ओफ़्फ़ "valueOf" के साथ ऑब्जेक्ट O की आंतरिक विधि [[गेट]] को कॉल करने का परिणाम है।

  1. यदि इस्कीबल (वैल्यूऑफ) सही है तो,

    1. मान लें कि [[कॉल]] कॉल करने का नतीजा है मूल्य मान की आंतरिक विधि, ओ के साथ यह मान और एक रिक्त तर्क सूची है।
    2. यदि वैल एक आदिम मान है, तो वैल लौटें।

यह कहने के सभी दौर का तरीका है कि ऑब्जेक्ट के valueOfफ़ंक्शन को कॉल किया जाता है और उस फ़ंक्शन से रिटर्न वैल्यू का उपयोग समीकरण में किया जाता है। यदि आप valueOfफ़ंक्शन को बदलना चाहते थे तो आप ऑपरेशन के परिणाम बदल सकते थे :

> five.valueOf = function () { return 10 }
undefined
> five * 5
50

10के रूप में fiveरों valueOfसमारोह में कोई बदलाव नहीं किया गया था, यह लिपटे आदिम मान देता है 5ताकि five * 5मूल्यांकन करने के लिए 5 * 5में जो परिणाम25

11fiveवस्तु की wtfसंपत्ति का मूल्यांकन किया जाता फिर जब उस पर सौंपा गया था से अपरिवर्तित होने के बावजूद 05

12 'potato'

13पोस्टफिक्स वृद्धि ऑपरेटर पर कहा जाता है five, जो संख्यात्मक मान हो जाता है ( 5, हम कवर कैसे पुराने), दुकानों मूल्य इतना है कि यह वापस किया जा सकता कहते हैं, 1मूल्य (करने के लिए 6), के लिए मूल्य प्रदान करती है five, और रिटर्न संग्रहीत मूल्य ( 5)

14 पहले की तरह, वापस किया गया मान बढ़ने से पहले का मान है

15चर पर संग्रहीत wtfआदिम मूल्य ( 6) की संपत्ति fiveतक पहुँचा जाता है। ES5 विनिर्देश की धारा 15.7.5 इस व्यवहार को परिभाषित करती है। संख्याओं से गुण मिलते हैं Number.prototype

16 Number.prototypeएक wtfसंपत्ति नहीं है , इसलिए undefinedवापस कर दिया है

17 five.wtfका मान दिया गया है 'potato?'असाइनमेंट ES5 विनिर्देश के 11.13.1 में परिभाषित किया गया है । मूल रूप से दिया गया मान लौटाया जाता है लेकिन संग्रहीत नहीं किया जाता है।

18 'potato?' असाइनमेंट ऑपरेटर द्वारा वापस कर दिया गया था

19फिर से five, जिस पर मूल्य का उपयोग 6होता है, और फिर से Number.prototypeएक wtfसंपत्ति नहीं होती है

20 undefined जैसा कि ऊपर बताया गया है

21 five पहुँचा है

22 6 में बताया गया है 13


17

यह बहुत आसान है।

function dis () { return this; }

यह thisसंदर्भ देता है। इसलिए, यदि आप ऐसा call(5)करते हैं तो आप एक ऑब्जेक्ट के रूप में नंबर पास कर रहे हैं।

callसमारोह तर्क की आपूर्ति नहीं करता है, पहला तर्क आप दे के संदर्भ है this। आम तौर पर अगर आप यह चाहते पर यह संदर्भ पर है, तो आप इसे देने के {}इतनाdis.call({}) है, जो साधन thisसमारोह में एक खाली है this। हालाँकि, यदि आप 5इसे पास करते हैं तो ऐसा लगता है कि यह किसी ऑब्जेक्ट में बदल जाएगा। देखें .call

तो वापसी है object

जब आप करते हैं five * 5, तो जावास्क्रिप्ट ऑब्जेक्ट fiveको आदिम प्रकार के रूप में देखता है , इसलिए इसके बराबर है 5 * 5। दिलचस्प है, करते हैं '5' * 5, यह अभी भी बराबर है25 , इसलिए जावास्क्रिप्ट स्पष्ट रूप से हुड के तहत कास्टिंग कर रहा है। इस लाइन पर अंतर्निहित fiveप्रकार में कोई परिवर्तन नहीं किया गया है

लेकिन जब आप ऐसा करते हैं तो ++यह ऑब्जेक्ट को आदिम numberप्रकार में परिवर्तित कर देगा जिससे .wtfसंपत्ति को हटा दिया जाएगा । क्योंकि आप अंतर्निहित प्रकार को प्रभावित कर रहे हैं


वापसी नंबर है
GSerg

++धर्मान्तरित और इसे वापस असाइन करता है। ++के बराबर है variable = variable + 1। तो आप ढीलेwtf
राजेश

*बनाम ++सब पर मुझे भ्रमित नहीं है। ऐसा फ़ंक्शन होने की उम्मीद है जो किसी भी तर्क और रिटर्न की उम्मीद नहीं करता thisहो, उस फ़ंक्शन को किसी भी तरह एक तर्क को स्वीकार करना और कुछ ऐसा लौटना है जो पसंद है, लेकिन वास्तव में, यह तर्क नहीं है - इससे मुझे कोई मतलब नहीं है।
नाथन लॉन्ग

यह क्या dis.call()करता है यह दिखाने के लिए इसे @NathanLong अपडेट किया गया ।
कैलम लेनिंगटन

5 ++ सी भाषा में समान व्यवहार करता है इसलिए आश्चर्य की कोई बात नहीं है। thisबस एक वस्तु के लिए एक सूचक है ताकि आदिम प्रकार अंतर्निहित रूप से परिवर्तित हो जाएं। बिना किसी तर्क के एक समारोह में कम से कम एक संदर्भ क्यों नहीं हो सकता है? संदर्भ सेट करने के लिए 1 का तर्क callया bindप्रयोग किया जाता है। इसके अलावा, फ़ंक्शन बंद हो जाते हैं जिसका अर्थ है कि उनके पास बस से अधिक की पहुंच हैarguments
Rivenfall

10

आदिम मूल्यों में संपत्ति नहीं हो सकती। लेकिन जब आप किसी संपत्ति को आदिम मूल्य पर एक्सेस करने का प्रयास करते हैं, तो यह पारदर्शी रूप से एक अस्थायी संख्या ऑब्जेक्ट को ट्रांसस्टाइप करता है।

इसलिए:

> function dis() { return this }
undefined
// Like five.dis(), so dis return the temporaty Number object and 
// reference it in five
> five = dis.call(5)
Number {[[PrimitiveValue]]: 5}

// Write the wtf attribut on the Number object referenced by five
> five.wtf = 'potato'
"potato"
// Read the wtf attribut on the Number object referenced by five
> five.wtf
"potato"

// Return 5*5 but dont change the reference of five
> five * 5
25
// Read the same wtf attribut on the Number object referenced by five
> five.wtf
"potato"

// Change the five reference to a new primitive value (5+1). Five
// reference a primitive now.
> five++
5

// Read the wtf attribut on a new temporary Number object construct from
// the primitive referenced by five. So wtf does not exist.
> five.wtf
undefined

// Write the wtf attribut on a new temporary Number object construct from
// the primitive referenced by five. But this object not referenced by
// five. It will be lost.
> five.wtf = 'potato?'
"potato?"

// Read the wtf attribut on a new temporary Number object construct from
// the primitive referenced by five. So wtf does not exist.
> five.wtf
undefined
> five
6

8

समारोह की घोषणा करें dis। समारोह इसका संदर्भ देता है

function dis() { return this }
undefined

disसंदर्भ के साथ बुलाओ 5। जब प्रचलित मोड ( एमडीएन ) में संदर्भ के रूप में पारित किया जाता है, तो आदिम मूल्यों को बॉक्सिंग किया जाता है । तो fiveअब ऑब्जेक्ट (बॉक्सिंग नंबर) है।

five = dis.call(5)
Number {[[PrimitiveValue]]: 5}

वैरिएबल wtfपर प्रॉपर्टी डिक्लेयर करेंfive

five.wtf = 'potato'
"potato"

का मूल्य five.wtf

five.wtf
"potato"

fiveबॉक्सिंग है 5, इसलिए यह एक ही समय में संख्या और ऑब्जेक्ट है (5 * 5 = 25)। यह नहीं बदलता है five

five * 5
25

का मूल्य five.wtf

five.wtf
"potato"

fiveयहां अनबॉक्सिंग हो रही है। fiveअब सिर्फ आदिम है number। यह प्रिंट करता है 5, और फिर जोड़ देता 1है five

five++
5

fiveअभी आदिम संख्या 6है, इसमें कोई गुण नहीं हैं।

five.wtf
undefined

आदिमों के पास गुण नहीं हो सकते हैं, आप इसे सेट नहीं कर सकते

five.wtf = 'potato?'
"potato?"

आप इसे नहीं पढ़ सकते, क्योंकि यह सेट नहीं था

five.wtf
undefined

fiveहै 6क्योंकि पोस्ट के ऊपर बढ़ाने की

five
6

7

पहले ऐसा लगता है कि यह नोडज कंसोल के माध्यम से चलाया जा रहा है।

1।

    function dis() { return this }

फ़ंक्शन डिस () बनाता है, लेकिन क्योंकि इसे सेट नहीं किया varगया था इसलिए लौटने का कोई मूल्य नहीं undefinedथा इसलिए आउटपुट था, भले ही dis()इसे परिभाषित किया गया था। thisइस कार्य को निष्पादित नहीं किए जाने के कारण , एक सिडेनोट पर वापस नहीं किया गया था।

2।

    five = dis.call(5)

यह जावास्क्रिप्ट की Numberवस्तु लौटाता है क्योंकि आप केवल फ़ंक्शन dis()का thisमान आदिम पाँच में सेट करते हैं ।

3।

   five.wtf = 'potato'

पहले रिटर्न "potato", क्योंकि आप बस गुण सेट wtfके fiveलिए 'potato'। जावास्क्रिप्ट आपके द्वारा सेट किए गए वैरिएबल का मान लौटाता है, जिससे कई वेरिएबल्स को चेन करना आसान हो जाता है और उन्हें इस तरह सेट किया जाता है:a = b = c = 2

4।

    five * 5

यह रिटर्न 25इसलिए है क्योंकि आपने अभी-अभी आदिम संख्या 5को गुणा किया है five। का मान वस्तु fiveके मूल्य द्वारा निर्धारित किया गया था Number

5।

    five.wtf

मैंने पहले इस लाइन को छोड़ दिया क्योंकि मैं इसे यहाँ दोहरा रहा हूँ। यह सिर्फ संपत्ति का मूल्य लौटाता हैwtf जिसे आपने ऊपर सेट किया है।

6।

    five++

जैसा कि @ कल्लुम ने कहा है, वस्तु से उसी मान से ++प्रकार परिवर्तित करेगाnumberNumber {[[PrimitiveValue]]: 5}}

अब क्योंकि fiveएक है number, आप तब तक इसके लिए गुण निर्धारित नहीं कर सकते जब तक आप ऐसा कुछ नहीं करते:

    five = dis.call(five)
    five.wtf = "potato?"

या

    five = { value: 6, wtf: "potato?" }

यह भी ध्यान दें कि दूसरे तरीके में पहली विधि का उपयोग करने की तुलना में अलग व्यवहार होगा क्योंकि यह Numberपहले बनाई गई वस्तु के बजाय एक सामान्य वस्तु को परिभाषित कर रहा है ।

मुझे आशा है कि यह मदद करता है, जावास्क्रिप्ट चीजों को ग्रहण करना पसंद करता है, इसलिए Numberऑब्जेक्ट से एक आदिम में बदलने के दौरान यह भ्रमित हो सकता है number। आप typeofकीवर्ड के उपयोग से टाइप करके देख सकते हैं कि टाइपऑफ़ पाँच लिखने के बाद, आप इसे वापस भेजते हैं 'object', और आपके द्वारा five++इसे रिटर्न करने के बाद 'number'

@ डिसेज़ संख्या वस्तु और आदिम संख्या के बीच अंतर को बहुत अच्छी तरह से वर्णन करता है।


6

जावास्क्रिप्ट स्कोप्स एक्ज़ेकशन कॉन्टेक्ट्स से बने होते हैं। प्रत्येक निष्पादन संदर्भ में एक लेक्सिकल पर्यावरण (बाहरी / विश्व स्तर पर स्कोप्ड मान), एक परिवर्तनीय पर्यावरण (स्थानीय रूप से स्कोप्ड मान), और यह एक बाध्यकारी है

इस बंधन निष्पादन प्रसंग का एक बहुत ही महत्वपूर्ण हिस्सा है। का उपयोग करना इस बंधनcall को बदलने का एक तरीका है , और ऐसा करने से स्वचालित रूप से बंधन को आबाद करने के लिए एक वस्तु का निर्माण होगा।

फ़ंक्शन .prototype.call () (MDN से)

वाक्य - विन्यास
fun.call(thisArg[, arg1[, arg2[, ...]]])

thisArg
मज़ा करने के लिए कॉल के लिए प्रदान की इस बात का मूल्य। ध्यान दें कि यह विधि द्वारा देखा गया वास्तविक मूल्य नहीं हो सकता है: यदि विधि गैर-सख्त मोड कोड में एक फ़ंक्शन है, तो अशक्त और अपरिभाषित को वैश्विक ऑब्जेक्ट के साथ बदल दिया जाएगा और आदिम मूल्यों को ऑब्जेक्ट में बदल दिया जाएगा । (जोर मेरा)

एक बार जब यह स्पष्ट हो जाए कि 5 में परिवर्तित किया जा रहा है new Number(5), तो बाकी को स्पष्ट होना चाहिए। ध्यान दें कि अन्य उदाहरण भी तब तक काम करेंगे जब तक वे आदिम मूल्य हैं।

function primitiveToObject(prim){
  return dis.call(prim);
}
function dis(){ return this; }

//existing example
console.log(primitiveToObject(5));

//Infinity
console.log(primitiveToObject(1/0));

//bool
console.log(primitiveToObject(1>0));

//string
console.log(primitiveToObject("hello world"));
<img src="http://i.stack.imgur.com/MUyRV.png" />

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


4

अवधारणाओं की एक जोड़ी समझाती है कि क्या होता है

5 एक संख्या है, एक आदिम मूल्य है

Number {[[PrimitiveValue]]: 5} संख्या का एक उदाहरण है (इसे ऑब्जेक्ट रैपर कहते हैं)

जब भी आप किसी संपत्ति / विधि को एक आदिम मूल्य पर एक्सेस करते हैं, तो JS इंजन उचित प्रकार (के Numberलिए 5, के Stringलिए 'str'और उसके Booleanलिए true) का ऑब्जेक्ट रैपर बनाएगा और उस ऑब्जेक्ट रैपर पर प्रॉपर्टी एक्सेस / मेथड कॉल को हल करेगा। ऐसा तब होता है जब आप true.toString()उदाहरण के लिए करते हैं।

वस्तुओं पर संचालन करते समय, वे उन कार्यों को हल करने के लिए आदिम मूल्यों (उपयोग करके toStringया valueOf) में परिवर्तित होते हैं - उदाहरण के लिए जब कर रहे हों

var obj = { a : 1 };
var string = 'mystr' + obj;
var number = 3 + obj;

stringकी स्ट्रिंग संयोजन का आयोजन करेगा mystrऔर obj.toString()और numberके अलावा आयोजन करेगा 3और obj.valueOf()

अब इसे सब एक साथ रखने के लिए

five = dis.call(5)

dis.call(5)(5).dis()यदि 5वास्तव में विधि होती तो ठीक वैसा ही व्यवहार करता dis। मेथड कॉल को हल करने के लिए, ऑब्जेक्ट रैपर बनाया जाता है और इस पर मेथड कॉल को हल किया जाता है। इस बिंदु पर आदिम मान 5 के आसपास एक वस्तु आवरण के पांच बिंदु।

five.wtf = 'potato'

एक वस्तु पर एक संपत्ति सेट करना, यहां कुछ भी नहीं फैंसी।

five * 5

यह वास्तव five.valueOf() * 5में ऑब्जेक्ट रैपर से आदिम मूल्य प्राप्त कर रहा है। fiveअभी भी प्रारंभिक वस्तु की ओर इशारा करता है।

five++

यह वास्तव में है five = five.valueOf() + 1इससे पहले कि यह रेखा fiveमान 5 के आसपास ऑब्जेक्ट रैपर रखती है, जबकि इस बिंदु के बाद fiveआदिम मान रखता है6

five.wtf
five.wtf = 'potato?'
five.wtf

fiveअब कोई वस्तु नहीं है। .wtfप्रॉपर्टी एक्सेस को हल करने के लिए उन लाइनों में से प्रत्येक संख्या का एक नया उदाहरण बनाता है । उदाहरण स्वतंत्र हैं, इसलिए एक पर एक संपत्ति स्थापित करना दूसरे पर दिखाई नहीं देगा। कोड पूरी तरह से इस एक के बराबर है:

(new Number(6)).wtf;
(new Number(6)).wtf = 'potato?';
(new Number(6)).wtf;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.