स्पष्ट जावास्क्रिप्ट सुविधाएँ

छवि


जब मैं जावास्क्रिप्ट भाषा की अल्पज्ञात विशेषताओं के बारे में अगला लेख पढ़ता हूं और चुपचाप ब्राउज़र कंसोल में कुछ पागल समाधान पेश करता हूं, तो मैं अक्सर अपने सिर में कहता हूं, ठीक है, ठेस पर, ज़ाहिर है, सब कुछ गलत है!? आखिरकार, भाषा ने लंबे समय से एक विशाल समुदाय का अधिग्रहण किया है और औद्योगिक विकास का एक आश्चर्यजनक व्यापक कवरेज है। यदि ऐसा है, तो हम अक्सर सभी को समझने की उनकी क्षमता के बारे में क्यों भूल जाते हैं और सचमुच इन सभी विशिष्ट और "यादगार" निर्माणों का प्रचार करते हैं? बस यह स्पष्ट है!


विषय पर तर्क करना


आप इस ग्राफोमेनिया को छोड़ सकते हैं।


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


यह कोई रहस्य नहीं है कि जावास्क्रिप्ट अपने लचीलेपन में अद्भुत है, जो कि इसका सबसे बड़ा गुण और कष्टप्रद अभिशाप है। जावास्क्रिप्ट डेवलपर का मार्ग लंबा और बेहद दिलचस्प है: हम पुस्तक को पुस्तक, लेख द्वारा लेख को अवशोषित करते हैं, और अद्वितीय अनुभव प्राप्त करते हैं, लेकिन कभी-कभी यह वास्तव में भाषा-विशिष्ट है। भाषा का व्यापक वितरण और एक ही समय में संचित और खिलाए गए गैर-स्पष्टता की एक समृद्ध संख्या दो मोर्चों के गठन में योगदान करती है: वे जो इस भाषा को लगभग मूर्तिमान करते हैं, और जो इसे एक अनाड़ी और स्वेच्छापूर्ण अधिकारों के रूप में देखते हैं।


और सभी ठीक होंगे, लेकिन अक्सर दोनों मोर्चों के प्रतिनिधि एक ही परियोजना पर काम कर रहे हैं। और हमेशा की तरह, सभी स्वीकृत अभ्यास गलतफहमी (समझने की अनिच्छा और यहां तक ​​कि अनदेखी) एक दूसरे के कोड हैं। और वास्तव में, "मुझे एक जावा डेवलपर मिला है, और यह आपका नहीं है!" । जावास्क्रिप्ट अनुयायियों ने खुद को आग में ईंधन जोड़ते हुए कहा, "कोई भी वास्तव में जावास्क्रिप्ट को नहीं जानता है!" हाँ "मैं इसे एक पंक्ति में js पर लिख सकता हूँ!" । मैं स्वीकार करता हूं कि मैं खुद अपने अवकाश पर असामान्य प्रोग्रामिंग का दुरुपयोग कर रहा हूं ...


आप इस समस्या को महसूस करना शुरू करते हैं जब आप सीमांत की जगह लेते हैं और बैरिकेड्स के दोनों तरफ लोगों और उनके कोड के साथ काम करने का कुछ अनुभव प्राप्त करते हैं। योजना और अन्य बैठकें अधिक उत्पादक होती हैं जब सभी डेवलपर्स न केवल व्यापारिक लाइनों के स्तर पर एक-दूसरे को समझते हैं, बल्कि उनके कार्यान्वयन के स्तर पर कम से कम थोड़ा सा। कुख्यात बास फैक्टर का परियोजना पर कम प्रभाव पड़ता है, जब एकल फ्रंट-एंडर की बीमारी की स्थिति में, शेष टीम .js फ़ाइल की कुछ लाइन को सही करने के लिए तिरस्कार नहीं करती है। टीम के भीतर और उससे परे ज्ञान साझा करने की प्रक्रिया हर किसी के लिए अधिक पारदर्शी हो जाती है जब सभी के पास अधिक विस्तृत तस्वीर होती है। अच्छी तरह से और सभी एक ही नस में।


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


बड़े हो रहे हैं और जिम्मेदारी ले रहे हैं


अपने हिस्से के लिए, जावास्क्रिप्ट ने लंबे समय से अपनी भूमिका का एहसास किया है, इंटरनेट पेजों की अन्तरक्रियाशीलता के लिए एक भाषा के रूप में नहीं और उनके संसाधनों को "gluing" करने के लिए, लेकिन संपूर्ण क्रॉस-प्लेटफ़ॉर्म और अक्सर बहुत ही स्केलेबल एप्लिकेशन बनाने के लिए एक शक्तिशाली और पर्याप्त उपकरण के रूप में।


मूल रूप से वेब डिजाइनरों के लिए डिज़ाइन किया गया, यह "सबसे गलत समझा प्रोग्रामिंग भाषा" तेजी से बढ़ती लोकप्रियता और प्रासंगिकता के बावजूद लंबे समय से पानी का प्रसार कर रहा है। 13-14 वर्षों के लिए ECMAScript 5.1 के संस्करण से पहले, मानक में किसी भी महत्वपूर्ण परिवर्तन को याद करना या इसके विकास के वेक्टर को समझना मुश्किल है। उस समय, उनके समुदाय ने भाषा के पारिस्थितिक तंत्र के निर्माण में बहुत बड़ा योगदान दिया: प्रोटोटाइप, jQuery, मूओसोल, आदि। डेवलपर्स से यह प्रतिक्रिया प्राप्त करने के बाद, जावास्क्रिप्ट ने बग्स पर महत्वपूर्ण काम किया: 2015 में ES6 की जोरदार 6-वर्षीय रिलीज और अब ECMAScript की वार्षिक रिलीज, TC39 समिति के विनिर्देशन के लिए नई सुविधाओं को पेश करने की प्रक्रिया को फिर से डिजाइन किया।


खैर, जब हमारे अनुप्रयोग काफी बड़े हो गए, तो उपयोगकर्ता प्रकारों का वर्णन करने के लिए प्रोटोटाइप ओओपी मॉडल अब असामान्य दृष्टिकोण के कारण उचित नहीं था। अच्छी तरह से गंभीरता से, यह क्या है?


function Animal() { /* Call me via new and I will be the constructor ;) */ } function Rabbit() {} Rabbit.prototype = Object.create(Animal.prototype); Rabbit.prototype.constructor = Rabbit; 

कक्षाएं भाषा में दिखाई नहीं दीं, लेकिन उनका वाक्य विन्यास दिखाई दिया। और कोड पारंपरिक वर्ग-उन्मुख प्रतिमान के अनुयायियों के लिए उपलब्ध हो गया है:


 class Animal { constructor() { /* Obviously, the constructor is here! */ } } class Rabbit extends Animal {} 

अब रिहाई के लिए उम्मीदवार के स्तर पर कक्षा के निजी क्षेत्र हैं । यह विश्वास करना कठिन है कि जितनी जल्दी या बाद में हम एक दूसरे के साथ निजी संपत्तियों का नामकरण करने पर सहमति के साथ हँसना बंद कर देंगे।


उसी समय, जिस भाषा में कोई फ़ंक्शन पहली-ऑर्डर ऑब्जेक्ट होता है और लगातार घटना होती है, वह काफी सामान्य है:


 let that = this; setTimeout(function() { that.n += 1; }, 1000); 

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


 setTimeout(() => this.n += 1, 1000); 

हमें एरो फ़ंक्शंस भी मिले, और ये वास्तव में फ़ंक्शंस हैं, न कि फ़ंक्शनल इंटरफेस (हाँ, जावा?)। एक सरणी के साथ काम करने के तरीकों के एक विस्तारित सेट के साथ, वे गणनाओं की सामान्य घोषणा पत्र लिखने में भी मदद करते हैं:


 [-1, 2, -3, 4] .filter(x => x > 0) .map(x => Math.pow(2, x)) .reduce((s, x) => s + x, 0); 

भाषा अपने आप को बहु-प्रतिमान मानती है। लेकिन यहाँ कुछ समारोह के हस्ताक्षर के बारे में एक सरल उदाहरण है:


 function ping(host, count) { count = count || 5; /* send ping to host count times */ } 

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


 function ping(host, count = 5) { /* ... */ } 

संक्षेप में, जावास्क्रिप्ट को बहुत सारी परिचित चीजें मिलीं: जनरेटर, पुनरावृत्तियों, संग्रह संग्रह और मानचित्र शब्दकोशों, टाइप किए गए सरणियों, और यहां तक ​​कि नियमित अभिव्यक्तियां भी समर्थन की तलाश करने लगीं ! भाषा कई चीजों के लिए उपयुक्त होने के लिए और सभी के लिए अनुकूल बनने के लिए सब कुछ करती है।


स्पष्ट के अनुकूल मार्ग


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


कास्टिंग टाइप करें


हां, जावास्क्रिप्ट में एक गतिशील और कमजोर प्रकार की प्रणाली है और आप किसी भी चीज पर परिचालन करने की अनुमति देते हैं, हमारे लिए अंतर्निहित रूप से परिवर्तन कर रहे हैं। लेकिन अक्सर, स्पष्ट कास्टिंग हमारे लिए अभी भी आवश्यक है, और निम्नलिखित देखे जा सकते हैं:


 let bool = !!(expr); let numb = +(expr); let str = ''+(expr); 

ये ट्रिक हर JavaScript डेवलपर को पता होती है और वे इस तथ्य से प्रेरित होते हैं कि वे कहते हैं कि आप "जल्दी से कुछ को कुछ में बदल सकते हैं": यहाँ गति से मतलब एक छोटा रिकॉर्ड है। क्या यह भी झूठा लिख सकता है ! 1 यदि डेवलपर मुद्रण योग्य वर्णों के बारे में चिंतित है, तो उसके पसंदीदा आईडीई में आप आसानी से आवश्यक लाइव टेम्पलेट या ऑटो-पूर्ण कॉन्फ़िगर कर सकते हैं। और अगर - प्रकाशित कोड के आकार के लिए, तो हम हमेशा इसे ओब्सफ्यूज़र के माध्यम से चलाते हैं, जो हमारे से बेहतर जानता है कि यह सब कैसे अमानवीय करना है। क्यों नहीं:


 let bool = Boolean(expr); let numb = Number(expr); let str = String(expr); 

परिणाम समान है, केवल सभी के लिए स्पष्ट है।


स्ट्रिंग रूपांतरणों के लिए, हमें स्ट्रगल करना होगा , लेकिन संख्यात्मक लोगों के लिए एक दिलचस्प मूल्य है, जिसे ओवरराइड भी किया जा सकता है। एक क्लासिक उदाहरण जो "अनइंस्टॉल" को एक स्तूप में पेश करता है:


 let timestamp = +new Date; 

लेकिन दिनांक एक ज्ञात getTime विधि है, का उपयोग करें:


 let timestamp = (new Date()).getTime(); 

या तैयार समारोह:


 let timestamp = Date.now(); 

निहित प्रकार के रूपांतरण का दोहन करने की बिल्कुल आवश्यकता नहीं है।


तार्किक संचालक


तार्किक ऑपरेटरों और (&&) और OR (()) पर विशेष ध्यान दिया जाता है, जो जावास्क्रिप्ट में काफी तार्किक नहीं हैं: वे किसी भी प्रकार के मूल्यों को स्वीकार करते हैं और वापस करते हैं। हम तार्किक अभिव्यक्ति कैलकुलेटर के संचालन के विवरण में नहीं जाएंगे , हम उदाहरणों पर विचार करेंगे। फ़ंक्शन के साथ पहले प्रस्तुत विकल्प:


 function ping(host, count) { count = count || 5; /* ... */ } 

यह इस तरह दिख सकता है:


 function ping(host, count) { // OR arguments.length? if (typeof count == 'undefined') { count = 5; } /* ... */ } 

इस तरह के सत्यापन अधिक परिचित हैं, और कुछ मामलों में गलतियों से बचने में मदद कर सकते हैं।


इसके बजाय, यह डेवलपर के लिए आश्‍चर्यजनक है जिसने शुरू में जावास्क्रिप्ट पथ को चुना था। लेकिन अधिकांश अन्य लोगों के लिए, यह कोड वास्तव में जंगली है:


 var root = (typeof self == 'object' && self.self === self && self) || (typeof global == 'object' && global.global === global && global); 

हां, यह कॉम्पैक्ट है, और हां, लोकप्रिय लाइब्रेरी इसे खरीद सकती हैं। लेकिन कृपया, इसका दुरुपयोग न करें, क्योंकि हमारे कोड को जावास्क्रिप्ट में योगदानकर्ताओं द्वारा नहीं पढ़ा जाएगा, लेकिन डेवलपर्स द्वारा जो समय सीमा में व्यावसायिक समस्याओं का समाधान करते हैं।


ऐसा पैटर्न बिल्कुल भी हो सकता है:


 let count = typeof opts == 'object' && opts.count || 5; 

यह निश्चित रूप से सामान्य टर्नरी ऑपरेटर की तुलना में कम है, लेकिन जब इस तरह के कोड को पढ़ते हैं, तो आपको जो पहली चीज याद आती है वह है इस्तेमाल किए गए संचालन की प्राथमिकताएं।


यदि हम एक विधेय फ़ंक्शन लिखते हैं, जिसे हम उसी Array.prototype.filter पर पास करते हैं, तो बूलियन में रिटर्न वैल्यू को लपेटना एक अच्छा स्वर है। इस फ़ंक्शन का उद्देश्य तुरंत स्पष्ट हो जाता है और डेवलपर्स के बीच कोई असंगति नहीं होती है, जिनकी भाषाओं में "सही" तार्किक ऑपरेटर होते हैं।


बिटवाइज ऑपरेशन


सरणी में किसी तत्व की उपस्थिति के लिए जाँच करने का एक सामान्य उदाहरण या बिटवाइज़ नॉट (NOT) का उपयोग करके स्ट्रिंग में प्रतिस्थापित करना, जो कुछ ट्यूटोरियल द्वारा भी प्रस्तुत किया जाता है:


 if (~[1, 2, 3].indexOf(1)) { console.log('yes'); } 

इससे क्या समस्या हल होती है? हमें जाँच नहीं करनी है ! == -1 , चूंकि indexOf को तत्व या -1 का सूचकांक मिलेगा, और टिल्ड 1 और परिवर्तन चिन्ह को जोड़ देगा। इस प्रकार, इंडेक्स -1 के मामले में अभिव्यक्ति "झूठ" में बदल जाएगी।


लेकिन कोड के दोहराव को दूसरे तरीके से टाला जा सकता है: कुछ बर्तनों-ऑब्जेक्ट के एक अलग फ़ंक्शन में चेक डालना, जैसा कि हर कोई करता है, अन्य उद्देश्यों के लिए बिटवाइज़ संचालन का उपयोग करने से। इसके लिए लॉश में एक फ़ंक्शन शामिल है , और इसके माध्यम से काम नहीं करता है नितंब टिल्ड। आप आनन्दित हो सकते हैं, क्योंकि ECMAScript 2016 में, Array.prototyp.includes विधि तय की गई है (लाइनों में एक भी है)।


लेकिन वहाँ यह था! एक अन्य टिल्ड (XOR के साथ) को गोल संख्या में उपयोग किया जाता है, जो दशमलव भाग को छोड़ देता है:


 console.log(~~3.14); // 3 console.log(2.72^0); // 2 

लेकिन इन उद्देश्यों के लिए parseInt या Math.floor है। कंसोल में टाइपिंग कोड के लिए यहां बिटवाइज़ ऑपरेशन सुविधाजनक हैं, क्योंकि बाकी अंकगणित पर भी उनकी प्राथमिकता कम है। लेकिन एक कोड की समीक्षा पर, इसे याद नहीं करना बेहतर है।


वाक्य रचना और भाषा निर्माण


कुछ अजीबोगरीब प्रथाएं किसी विशेष तबके के लिए मुश्किल होती हैं। उदाहरण के लिए, वे कहते हैं कि कंस्ट्रक्टर को कॉल करते समय कोष्ठक वैकल्पिक हैं, और निम्नलिखित दो भाव समान हैं:


 let rabbit = new Rabbit(); let rabbit = new Rabbit; 

और यह वास्तव में है! लेकिन खरोंच से एक सवाल क्यों? हर भाषा ऐसी "सुविधा" का दावा नहीं कर सकती। और अगर आप अभी भी चाहते हैं, तो इसे पूरी परियोजना पर एक समझौता होने दें। अन्यथा, एक झूठी भावना है कि कुछ अंतर है।


चर का एक सेट घोषित करने के साथ एक समान स्थिति। Var का सिंटैक्स और निर्देश आपको एक बार में कई वैरिएबल घोषित करने (और परिभाषित) करने की अनुमति देता है, जिन्हें अल्पविराम द्वारा अलग किया जाता है:


 let count = 5, host, retry = true; 

कोई पठनीयता के लिए लाइन फ़ीड का उपयोग करता है, लेकिन किसी भी मामले में, लोकप्रिय भाषाओं में यह वाक्यविन्यास आम नहीं है। कोई भी हाथ नहीं देगा और पूछेगा कि क्या आप इस तरह लिखते हैं:


 let count = 5; let retry = true; let host; 

फिर, अगर परियोजना / कंपनी के स्तर पर अच्छी शैली पर एक समझौता है, तो कोई सवाल नहीं है। यह सिर्फ इतना है कि आपको अपने मूड के लिए बहुत अधिक वाक्यविन्यास को संयोजित नहीं करना है।


भाषा में विशिष्ट निर्माण हैं, जैसे कि IIFE, जो आपको इसकी परिभाषा के स्थान पर तुरंत एक फ़ंक्शन को कॉल करने की अनुमति देता है। ट्रॉलर पार्सर के लिए एक कार्यात्मक अभिव्यक्ति को पहचानने के लिए है, न कि एक फ़ंक्शन घोषणा। और यह बहुत से अलग-अलग तरीकों से किया जा सकता है: कोष्ठक में लपेटकर, शून्य या किसी अन्य गैरी ऑपरेटर के माध्यम से। और इसके बारे में कुछ भी अद्भुत नहीं है! केवल विकल्प चुनना आवश्यक है और आवश्यकता के बिना इसे नहीं छोड़ना है:


 (function() { /* ... */ }()); 

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


ES6 में क्लास सिंटैक्स की उपस्थिति सामान्य एक्सेस मॉडिफायर्स के साथ नहीं थी। और कभी-कभी डेवलपर कक्षाओं में पेशाब करना और गोपनीयता का पालन करना चाहता है। जो इस फ्रेंकस्टीन कोड की ओर जाता है:


 class Person { constructor(name) { let _name = name; this.getName = function() { return _name; } } toString() { return `Hello, ${this.getName()}`; } } 

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


सारांशित करते हुए, वह परियोजना में अपनाई गई शैली गाइड, लिंटर के लिए कॉन्फ़िगरेशन या सहकर्मियों के साथ कोड अंशों को साझा करेगा, जो परियोजना में इसके गैर-जावास्क्रिप्ट घटक का योगदान करते हैं। भाषा वस्तुतः हर विशिष्ट कार्य के लिए कई विकल्प प्रदान करती है, इसलिए एक-दूसरे की समझ में सुधार करना और एक सामान्य भाजक के तहत गिरना मुश्किल नहीं है (या लगभग)।


दुर्भाग्य


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

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


All Articles