इसमें क्या लिखा है? जावास्क्रिप्ट वस्तुओं के दृश्यों के पीछे

जावास्क्रिप्ट एक बहु-प्रतिमान भाषा है जो ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग और डायनामिक मेथड बाइंडिंग को सपोर्ट करती है - एक शक्तिशाली कॉन्सेप्ट जो जावास्क्रिप्ट कोड की संरचना को प्रोग्राम एक्जीक्यूशन के दौरान बदलने की अनुमति देता है। यह डेवलपर्स को गंभीर अवसर देता है, यह भाषा को लचीला बनाता है, लेकिन आपको हर चीज के लिए भुगतान करना होगा। इस मामले में, आपको कोड की समझदारी के साथ भुगतान करना होगा। इस मूल्य के लिए एक महत्वपूर्ण योगदान this द्वारा किया जाता है, जिसके व्यवहार के आसपास बहुत सारी चीजें एकत्र की गई हैं जो प्रोग्रामर को भ्रमित कर सकती हैं।



गतिशील विधि बाइंडिंग


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

चलो एक खेल खेलते हैं। मैं इसे "इसमें क्या लिखा है?" कहता हूं। यहाँ उसका पहला विकल्प है - ES6 मॉड्यूल कोड:

 const a = { a: 'a' }; const obj = { getThis: () => this, getThis2 () {   return this; } }; obj.getThis3 = obj.getThis.bind(obj); obj.getThis4 = obj.getThis2.bind(obj); const answers = [ obj.getThis(), obj.getThis.call(a), obj.getThis2(), obj.getThis2.call(a), obj.getThis3(), obj.getThis3.call(a), obj.getThis4(), obj.getThis4.call(a) ]; 

आगे पढ़ने से पहले, इस बारे में सोचें कि उत्तर सरणी में क्या आएगा और उत्तर लिखिए। ऐसा करने के बाद, console.log() का उपयोग करके answers सरणी को answers करके स्वयं का परीक्षण करें। क्या आपने प्रत्येक मामले में इसके मूल्य को सही ढंग से "डिक्रिप्ट" करने का प्रबंधन किया था?

हम पहले उदाहरण के साथ शुरू करते हुए, इस समस्या का विश्लेषण करेंगे। obj.getThis() निर्माण undefined । क्यों? यह तीर फ़ंक्शन बाध्य नहीं किया जा सकता है। इस तरह के फ़ंक्शंस इसका उपयोग उनके आसपास के शाब्दिक दायरे से करते हैं। विधि को ES6 मॉड्यूल में कहा जाता है, इसके शाब्दिक दायरे में this undefined होगा। उसी कारण से, undefined obj.getThis.call(a) लिए कॉल obj.getThis.call(a) । तीर फ़ंक्शन के साथ काम करने पर इसका मान .call() या .bind() साथ भी पुन: असाइन नहीं किया जा सकता है। यह मान हमेशा शाब्दिक दायरे से इसके अनुरूप होगा, जिसमें ऐसे कार्य स्थित हैं।

obj.getThis2() कमांड यह प्रदर्शित करता है कि नियमित ऑब्जेक्ट विधियों का उपयोग करते समय इसके साथ कैसे काम किया जाए। यदि this एक समान विधि से बंधा नहीं है, और बशर्ते कि यह विधि एक तीर फ़ंक्शन नहीं है, अर्थात, यह this बंधन का समर्थन करता है, तो this कीवर्ड उस ऑब्जेक्ट के लिए बाध्य है जिसके लिए विधि के गुणों के उपयोग के सिंटैक्स का उपयोग करके कहा जाता है वर्ग कोष्ठक का उपयोग करना।

obj.getThis2.call(a) निर्माण पहले से ही पता लगाने के लिए थोड़ा पेचीदा मामला है। call() विधि आपको दिए गए मान के साथ एक फ़ंक्शन को कॉल करने की अनुमति देती है, जिसे वैकल्पिक तर्क के रूप में दर्शाया गया है। दूसरे शब्दों में, इस मामले में, this .call() पैरामीटर से लिया गया है, परिणामस्वरूप, obj.getThis2.call(a) लिए कॉल ऑब्जेक्ट a लौटाता a

कमांड का उपयोग करना obj.getThis3 = obj.getThis.bind(obj); हम this पद्धति से जुड़ने की कोशिश कर रहे हैं, जो एक तीर का कार्य है। जैसा कि हमने पहले ही पता लगा लिया है, ऐसा नहीं किया जा सकता है। नतीजतन, obj.getThis3() और obj.getThis3.call(a) लिए कॉल obj.getThis3() लौटते हैं।

सामान्य कार्य करने वाली विधियाँ इससे जुड़ी हो सकती हैं, इसलिए obj.getThis4() , जैसा कि अपेक्षित है, obj देता है। एक कॉल obj.getThis4.call(a) रिटर्न obj , और नहीं, जैसा कि आप उम्मीद कर सकते हैं, a । तथ्य यह है कि इस आदेश को obj.getThis4 = obj.getThis2.bind(obj); से पहले, हम पहले से ही obj.getThis4 = obj.getThis2.bind(obj); कमांड के साथ this बाध्य this obj.getThis4 = obj.getThis2.bind(obj); । नतीजतन, जब obj.getThis4.call(a) निष्पादित करते हैं, तो उस विधि की स्थिति जिसमें वह पहले बाध्यकारी होने के बाद खाते में लिया जाता है।

कक्षाओं में इसका उपयोग करना


यहां हमारे खेल का दूसरा संस्करण है - समान कार्य, लेकिन अब कक्षाओं पर आधारित है। यहां हम सार्वजनिक वर्ग के फ़ील्ड घोषित करने के लिए सिंटैक्स का उपयोग करते हैं (फिलहाल, इस सिंटैक्स का प्रस्ताव अनुमोदन के तीसरे चरण में है, यह क्रोम में डिफ़ॉल्ट रूप से उपलब्ध है, आप इसे @babel/plugin-proposal-class-properties साथ उपयोग कर सकते हैं)।

 class Obj { getThis = () => this getThis2 () {   return this; } } const obj2 = new Obj(); obj2.getThis3 = obj2.getThis.bind(obj2); obj2.getThis4 = obj2.getThis2.bind(obj2); const answers2 = [ obj2.getThis(), obj2.getThis.call(a), obj2.getThis2(), obj2.getThis2.call(a), obj2.getThis3(), obj2.getThis3.call(a), obj2.getThis4(), obj2.getThis4.call(a) ]; 

आगे पढ़ने से पहले, कोड के बारे में सोचें और उत्तर answers2 सरणी में क्या गिरेंगे अपनी दृष्टि लिखें।

हो गया ना?

यहां, obj2.getThis2.call(a) को छोड़कर सभी विधि कॉल, ऑब्जेक्ट के उदाहरण के लिए एक संदर्भ लौटाएंगे। एक ही कॉल वस्तु वापस कर देगा। एरो फ़ंक्शंस अभी भी इसे लेक्सिकल स्कोप से लेते हैं। इस उदाहरण और पिछले एक के बीच का अंतर उस दायरे से अंतर है जिसमें से this लिया गया है।

अर्थात्, यहाँ हम वर्ग गुणों के साथ काम करते हैं, जो इस कोड के व्यवहार को निर्धारित करता है।

तथ्य यह है कि निष्पादन के लिए कोड की तैयारी के दौरान, इस तरह के वर्गों के गुणों के लिए मान लिखे गए हैं:

 class Obj { constructor() {   this.getThis = () => this; } ... 

दूसरे शब्दों में, यह पता चलता है कि तीर फ़ंक्शन को कंस्ट्रक्टर फ़ंक्शन के संदर्भ में घोषित किया गया है। चूँकि हम एक वर्ग के साथ काम कर रहे हैं, इसलिए इसे त्वरित करने का एकमात्र तरीका new कीवर्ड का उपयोग करना है (यदि आप इस कीवर्ड के बारे में भूल जाते हैं, तो एक त्रुटि संदेश प्रदर्शित होगा)।

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

परिणाम


क्या आपने इस लेख में उल्लिखित कार्यों को पूरा किया है? जब this कीवर्ड जावास्क्रिप्ट में व्यवहार करता है, तो एक अच्छी समझ आपको डीबग करने के समय की एक टन बचत होगी, जब अस्पष्ट त्रुटियों के लिए गैर-स्पष्ट कारणों की तलाश होती है। यदि आपने कुछ प्रश्नों के गलत उत्तर दिए हैं, तो इसका मतलब है कि यह आपके लिए अभ्यास करने के लिए उपयोगी होगा।

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

अगर यह सब आपको आपकी अपेक्षा से अधिक जटिल लगता है, तो जान लें कि आप इसमें अकेले नहीं हैं। मैंने this की विशेषताओं के ज्ञान के लिए काफी कुछ डेवलपर्स का परीक्षण किया, और मुझे लगता है कि उनमें से केवल एक ही उनके सभी उत्तरों में बिल्कुल सटीक था।

भाषा का वह सबसिस्टम, जो बहुत शुरुआत में उन विधियों के लिए एक गतिशील खोज की तरह दिखता था, जिनका उपयोग करके प्रभावित किया जा सकता है .apply() , .apply() या .apply() , तीर फ़ंक्शंस और कक्षाओं की उपस्थिति के बाद बहुत अधिक जटिल .apply() लगे।

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

यह भी याद रखें कि आप अपने कोड में this उपयोग किए बिना जावास्क्रिप्ट में बहुत कुछ कर सकते हैं। अनुभव मुझे बताता है कि लगभग किसी भी जेएस कोड को शुद्ध कार्यों के रूप में फिर से लिखा जा सकता है जो उन सभी तर्कों को स्वीकार करते हैं जिनके साथ वे काम करते हैं, स्पष्ट रूप से निर्दिष्ट मापदंडों की सूची के रूप में ( this एक उत्परिवर्ती राज्य के साथ एक स्पष्ट रूप से निर्दिष्ट पैरामीटर के रूप में समझा जा सकता है)। शुद्ध कार्यों में निहित तर्क नियतात्मक है, जो उनकी परीक्षण क्षमता में सुधार करता है। इस तरह के कार्यों के साइड इफेक्ट्स नहीं होते हैं, जिसका अर्थ है कि उनके साथ काम करते समय, this हेरफेर के विपरीत, आपको इसके बाहर कुछ भी "ब्रेक" करने की संभावना नहीं है। जब भी आप इसे बदलते हैं, तो आपको एक संभावित समस्या का सामना करना पड़ता है, जो यह है कि ऐसा कुछ जो इस पर निर्भर करता है, सही तरीके से काम करना बंद कर सकता है।

उपरोक्त के बावजूद, यह ध्यान दिया जाना चाहिए कि this एक उपयोगी अवधारणा है। उदाहरण के लिए, वस्तुओं की भीड़ द्वारा एक निश्चित विधि के साझाकरण को व्यवस्थित करने के लिए इसे लागू किया जा सकता है। फ़ंक्शनल प्रोग्रामिंग में भी, this एक ऑब्जेक्ट के एक तरीके से अन्य तरीकों को कॉल करने के लिए काम में आ सकता है, जो आपको कुछ नए निर्माणों के आधार पर कुछ नया बनाने की अनुमति देता है।



Source: https://habr.com/ru/post/hi455527/


All Articles