JavaScript

इवेंट डेलिगेशन की व्याख्या करें

इवेंट डेलिगेशन एक ऐसी तकनीक है जिसमें वंशज तत्वों के बजाय एक पैरेंट तत्व में इवेंट श्रोताओं को जोड़ना शामिल है। इवेंट DOM में बबलिंग के कारण वंशज तत्वों पर इवेंट ट्रिगर होने पर श्रोता फायर करेगा। इस तकनीक के लाभ हैं:

  • मेमोरी फ़ुटप्रिंट कम हो जाता है क्योंकि पैरेंट तत्व पर केवल एक ही हैंडलर की आवश्यकता होती है, बजाय इसके कि प्रत्येक वंशज पर इवेंट हैंडलर को संलग्न करना पड़े।
  • हटाए गए तत्वों से हैंडलर को अनबाइंड करने और नए तत्वों के लिए इवेंट को बाइंड करने की कोई आवश्यकता नहीं है।

जावास्क्रिप्ट में `this` कैसे काम करता है, इसकी व्याख्या करें

this के लिए कोई सरल व्याख्या नहीं है; यह जावास्क्रिप्ट में सबसे भ्रमित करने वाली अवधारणाओं में से एक है। एक हाथ-लहराती व्याख्या यह है कि this का मान फ़ंक्शन को कैसे कॉल किया जाता है, इस पर निर्भर करता है। मैंने this पर ऑनलाइन कई व्याख्याएं पढ़ी हैं, और मुझे [अर्नव अग्रवाल] की व्याख्या सबसे स्पष्ट लगी। निम्नलिखित नियम लागू होते हैं:

  1. यदि फ़ंक्शन को कॉल करते समय new कीवर्ड का उपयोग किया जाता है, तो फ़ंक्शन के अंदर this एक बिल्कुल नया ऑब्जेक्ट होता है।
  2. यदि apply, call, या bind का उपयोग किसी फ़ंक्शन को कॉल/बनाने के लिए किया जाता है, तो फ़ंक्शन के अंदर this वह ऑब्जेक्ट होता है जिसे तर्क के रूप में पारित किया जाता है।
  3. यदि किसी फ़ंक्शन को एक विधि के रूप में कॉल किया जाता है, जैसे कि obj.method() - this वह ऑब्जेक्ट है जिसका फ़ंक्शन एक गुण है।
  4. यदि किसी फ़ंक्शन को एक फ्री फ़ंक्शन इनवोकेशन के रूप में इनवोक किया जाता है, जिसका अर्थ है कि इसे ऊपर मौजूद किसी भी शर्त के बिना इनवोक किया गया था, तो this वैश्विक ऑब्जेक्ट है। एक ब्राउज़र में, यह window ऑब्जेक्ट है। यदि सख्त मोड ('use strict') में है, तो this वैश्विक ऑब्जेक्ट के बजाय undefined होगा।
  5. यदि उपरोक्त कई नियम लागू होते हैं, तो जो नियम उच्च होता है वह जीतता है और this मान सेट करेगा।
  6. यदि फ़ंक्शन एक ES2015 एरो फ़ंक्शन है, तो यह ऊपर के सभी नियमों को अनदेखा करता है और इसके बनने के समय इसके आसपास के स्कोप का this मान प्राप्त करता है।

गहन व्याख्या के लिए, मीडियम पर उसका [लेख] देखें।

क्या आप ES6 में this के साथ काम करने के तरीकों में से एक का उदाहरण दे सकते हैं?

ES6 आपको [एरो फ़ंक्शंस] का उपयोग करने की अनुमति देता है जो [संलग्न लेक्सिकल स्कोप] का उपयोग करता है। यह आमतौर पर सुविधाजनक होता है, लेकिन कॉलर को .call या .apply के माध्यम से संदर्भ को नियंत्रित करने से रोकता है - जिसके परिणामस्वरूप jQuery जैसी लाइब्रेरी आपके इवेंट हैंडलर फ़ंक्शंस में this को ठीक से बाइंड नहीं करेगी। इस प्रकार, बड़े विरासत अनुप्रयोगों को फिर से फ़ैक्टर करते समय इसे ध्यान में रखना महत्वपूर्ण है।

प्रोटोटाइपिक इनहेरिटेंस कैसे काम करता है, इसकी व्याख्या करें

ऑब्जेक्ट्स के साथ बनाए गए ऑब्जेक्ट्स को छोड़कर सभी जावास्क्रिप्ट ऑब्जेक्ट्स में एक __proto__ प्रॉपर्टी होती है, Object.create(null) के साथ बनाए गए ऑब्जेक्ट्स को छोड़कर, जो एक अन्य ऑब्जेक्ट का संदर्भ होता है, जिसे ऑब्जेक्ट का "प्रोटोटाइप" कहा जाता है। जब किसी ऑब्जेक्ट पर किसी प्रॉपर्टी को एक्सेस किया जाता है और यदि प्रॉपर्टी उस ऑब्जेक्ट पर नहीं मिलती है, तो जावास्क्रिप्ट इंजन ऑब्जेक्ट के __proto__ को देखता है, और __proto__ के __proto__ को देखता है, और इसी तरह, जब तक उसे __proto__ में से किसी एक पर परिभाषित प्रॉपर्टी नहीं मिल जाती या जब तक वह प्रोटोटाइप चेन के अंत तक नहीं पहुंच जाता। यह व्यवहार क्लासिकल इनहेरिटेंस का अनुकरण करता है, लेकिन यह वास्तव में [इनहेरिटेंस से अधिक डेलिगेशन] है।

प्रोटोटाइपिक इनहेरिटेंस का उदाहरण

// पैरेंट ऑब्जेक्ट कंस्ट्रक्टर। function Animal(name) { this.name = name; } // पैरेंट ऑब्जेक्ट के प्रोटोटाइप में एक विधि जोड़ें। Animal.prototype.makeSound = function () { console.log('The ' + this.constructor.name + ' makes a sound.'); }; // चाइल्ड ऑब्जेक्ट कंस्ट्रक्टर। function Dog(name) { Animal.call(this, name); // पैरेंट कंस्ट्रक्टर को कॉल करें। } // चाइल्ड ऑब्जेक्ट के प्रोटोटाइप को पैरेंट के प्रोटोटाइप पर सेट करें। Object.setPrototypeOf(Dog.prototype, Animal.prototype); // चाइल्ड ऑब्जेक्ट के प्रोटोटाइप में एक विधि जोड़ें। Dog.prototype.bark = function () { console.log('Woof!'); }; // Dog का एक नया इंस्टेंस बनाएं। const bolt = new Dog('Bolt'); // चाइल्ड ऑब्जेक्ट पर विधियों को कॉल करें। console.log(bolt.name); // "Bolt" bolt.makeSound(); // "The Dog makes a sound." bolt.bark(); // "Woof!"

ध्यान देने योग्य बातें हैं:

  • .makeSound Dog पर परिभाषित नहीं है, इसलिए इंजन प्रोटोटाइप चेन से ऊपर जाता है और इनहेरिटेड Animal से .makeSound पाता है।
  • इनहेरिटेंस चेन बनाने के लिए Object.create का उपयोग अब अनुशंसित नहीं है। इसके बजाय Object.setPrototypeOf का उपयोग करें।

आप एएमडी बनाम कॉमनजेएस के बारे में क्या सोचते हैं?

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

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

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

बताइए कि निम्नलिखित IIFE के रूप में काम क्यों नहीं करता: `function foo(){ }();`। इसे ठीक से IIFE बनाने के लिए क्या बदलने की आवश्यकता है?

IIFE का अर्थ है तुरंत इनवोक किए गए फ़ंक्शन एक्सप्रेशंस। जावास्क्रिप्ट पार्सर function foo(){ }(); को function foo(){ } और (); के रूप में पढ़ता है, जहां पहला एक फ़ंक्शन घोषणा है और बाद वाला (एक जोड़ी कोष्ठक) एक फ़ंक्शन को कॉल करने का प्रयास है, लेकिन कोई नाम निर्दिष्ट नहीं है, इसलिए यह अनकैच सिंटैक्सएरर: अनपेक्षित टोकन ) फेंकता है।

यहां इसे ठीक करने के दो तरीके दिए गए हैं जिनमें और कोष्ठक जोड़ना शामिल है: (function foo(){ })() और (function foo(){ }())function से शुरू होने वाले स्टेटमेंट को फ़ंक्शन घोषणाएं माना जाता है; इस फ़ंक्शन को () के भीतर लपेटने से, यह एक फ़ंक्शन एक्सप्रेशन बन जाता है जिसे बाद में subsequent () के साथ निष्पादित किया जा सकता है। ये फ़ंक्शन वैश्विक दायरे में उजागर नहीं होते हैं और यदि आपको शरीर के भीतर खुद को संदर्भित करने की आवश्यकता नहीं है तो आप इसका नाम भी छोड़ सकते हैं।

आप void ऑपरेटर का भी उपयोग कर सकते हैं: void function foo(){ }();। दुर्भाग्य से, इस तरह के दृष्टिकोण में एक समस्या है। दिए गए एक्सप्रेशन का मूल्यांकन हमेशा undefined होता है, इसलिए यदि आपका IIFE फ़ंक्शन कुछ भी लौटाता है, तो आप उसका उपयोग नहीं कर सकते। एक उदाहरण:

const foo = void (function bar() { return 'foo'; })(); console.log(foo); // undefined

एक वैरिएबल जो: `null`, `undefined` या अनडिक्लेयर्ड है, के बीच क्या अंतर है? आप इनमें से किसी भी स्थिति की जांच कैसे करेंगे?

अनडिक्लेयर्ड वैरिएबल तब बनाए जाते हैं जब आप किसी ऐसे पहचानकर्ता को मान असाइन करते हैं जिसे पहले var, let या const का उपयोग करके नहीं बनाया गया है। अनडिक्लेयर्ड वैरिएबल को वर्तमान स्कोप के बाहर, वैश्विक रूप से परिभाषित किया जाएगा। सख्त मोड में, जब आप किसी अनडिक्लेयर्ड वैरिएबल को असाइन करने का प्रयास करेंगे तो एक रेफरेंसएरर फेंक दिया जाएगा। अनडिक्लेयर्ड वैरिएबल बुरे हैं जैसे कि वैश्विक वैरिएबल बुरे हैं। हर कीमत पर उनसे बचें! उनकी जांच करने के लिए, उनके उपयोग को एक try/catch ब्लॉक में लपेटें।

function foo() { x = 1; // सख्त मोड में एक रेफरेंसएरर फेंकता है } foo(); console.log(x); // 1

एक वैरिएबल जो undefined है वह एक ऐसा वैरिएबल है जिसे घोषित किया गया है, लेकिन कोई मान असाइन नहीं किया गया है। यह undefined प्रकार का है। यदि कोई फ़ंक्शन इसे निष्पादित करने के परिणामस्वरूप कोई मान नहीं लौटाता है जिसे एक वैरिएबल को असाइन किया जाता है, तो वैरिएबल का मान भी undefined होता है। इसकी जांच करने के लिए, सख्त समानता (===) ऑपरेटर या typeof का उपयोग करके तुलना करें जो 'undefined' स्ट्रिंग देगा। ध्यान दें कि आपको जांच के लिए अमूर्त समानता ऑपरेटर का उपयोग नहीं करना चाहिए, क्योंकि यदि मान null है तो यह भी true लौटाएगा।

var foo; console.log(foo); // undefined console.log(foo === undefined); // true console.log(typeof foo === 'undefined'); // true console.log(foo == null); // true। गलत, इसकी जांच के लिए इसका उपयोग न करें! function bar() {} var baz = bar(); console.log(baz); // undefined

एक वैरिएबल जो null है उसे स्पष्ट रूप से null मान पर असाइन किया गया होगा। यह कोई मान नहीं दर्शाता है और इस अर्थ में undefined से भिन्न है कि इसे स्पष्ट रूप से असाइन किया गया है। null की जांच करने के लिए, बस सख्त समानता ऑपरेटर का उपयोग करके तुलना करें। ध्यान दें कि ऊपर की तरह, आपको जांच के लिए अमूर्त समानता ऑपरेटर (==) का उपयोग नहीं करना चाहिए, क्योंकि यदि मान undefined है तो यह भी true लौटाएगा।

var foo = null; console.log(foo === null); // true console.log(typeof foo === 'object'); // true console.log(foo == undefined); // true। गलत, इसकी जांच के लिए इसका उपयोग न करें!

एक व्यक्तिगत आदत के रूप में, मैं अपने वैरिएबल को कभी भी अनडिक्लेयर्ड या अनअसाइन नहीं छोड़ता। यदि मैं अभी तक इसका उपयोग करने का इरादा नहीं रखता तो मैं उन्हें घोषित करने के बाद स्पष्ट रूप से null असाइन कर दूंगा। यदि आप अपने वर्कफ़्लो में एक लिंटर का उपयोग करते हैं, तो वह आमतौर पर यह जांचने में भी सक्षम होगा कि आप अनडिक्लेयर्ड वैरिएबल को संदर्भित नहीं कर रहे हैं।

क्लोजर क्या है, और आप इसका उपयोग कैसे/क्यों करेंगे?

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

आप इसका उपयोग क्यों करेंगे?

  • डेटा गोपनीयता / क्लोजर के साथ निजी विधियों का अनुकरण करना। आमतौर पर [मॉड्यूल पैटर्न] में उपयोग किया जाता है।
  • [आंशिक अनुप्रयोग या करिंग]।

क्या आप `.forEach` लूप और `.map()` लूप के बीच मुख्य अंतर बता सकते हैं और आप एक के बजाय दूसरे को क्यों चुनेंगे?

दोनों के बीच के अंतर को समझने के लिए, आइए देखें कि प्रत्येक फ़ंक्शन क्या करता है।

forEach

  • एक ऐरे में तत्वों के माध्यम से पुनरावृति करता है।
  • प्रत्येक तत्व के लिए एक कॉलबैक निष्पादित करता है।
  • कोई मान नहीं लौटाता है।
const a = [1, 2, 3]; const doubled = a.forEach((num, index) => { // num और/या index के साथ कुछ करें। }); // doubled = undefined

map

  • एक ऐरे में तत्वों के माध्यम से पुनरावृति करता है।
  • प्रत्येक तत्व पर फ़ंक्शन को कॉल करके प्रत्येक तत्व को एक नए तत्व पर "मैप" करता है, जिसके परिणामस्वरूप एक नया ऐरे बनता है।
const a = [1, 2, 3]; const doubled = a.map((num) => { return num * 2; }); // doubled = [2, 4, 6]

.forEach और .map() के बीच मुख्य अंतर यह है कि .map() एक नया ऐरे लौटाता है। यदि आपको परिणाम की आवश्यकता है, लेकिन मूल ऐरे को बदलना नहीं चाहते हैं, तो .map() स्पष्ट विकल्प है। यदि आपको केवल एक ऐरे पर पुनरावृति करने की आवश्यकता है, तो forEach एक अच्छा विकल्प है।

गुमनाम कार्यों के लिए एक विशिष्ट उपयोग का मामला क्या है?

उनका उपयोग IIFE में कुछ कोड को एक स्थानीय दायरे में समाहित करने के लिए किया जा सकता है ताकि इसमें घोषित वैरिएबल वैश्विक दायरे में लीक न हों।

(function () { // यहां कुछ कोड। })();

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

setTimeout(function () { console.log('नमस्ते दुनिया!'); }, 1000);

कार्यात्मक प्रोग्रामिंग कंस्ट्रक्ट्स या Lodash (कॉलबैक के समान) के लिए तर्क।

const arr = [1, 2, 3]; const double = arr.map(function (el) { return el * 2; }); console.log(double); // [2, 4, 6]

आप अपने कोड को कैसे व्यवस्थित करते हैं? (मॉड्यूल पैटर्न, क्लासिकल इनहेरिटेंस?)

अतीत में, मैंने अपने मॉडलों के लिए बैकबोन का उपयोग किया है जो अधिक OOP दृष्टिकोण को प्रोत्साहित करता है, बैकबोन मॉडल बनाता है और उनमें विधियों को संलग्न करता है।

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

मैं जहां संभव हो, क्लासिकल इनहेरिटेंस का उपयोग करने से बचता हूं। जब और यदि मैं करता हूं, तो मैं [इन नियमों] पर टिके रहता हूं।

होस्ट ऑब्जेक्ट और नेटिव ऑब्जेक्ट में क्या अंतर है?

नेटिव ऑब्जेक्ट वे ऑब्जेक्ट होते हैं जो ECMAScript स्पेसिफिकेशन द्वारा परिभाषित जावास्क्रिप्ट भाषा का हिस्सा होते हैं, जैसे String, Math, RegExp, Object, Function, आदि।

होस्ट ऑब्जेक्ट रनटाइम वातावरण (ब्राउज़र या नोड) द्वारा प्रदान किए जाते हैं, जैसे window, XMLHTTPRequest, आदि।

अंतर: `function Person(){}`, `var person = Person()`, और `var person = new Person()`?

यह प्रश्न काफी अस्पष्ट है। इसका इरादा यह है कि यह जावास्क्रिप्ट में कंस्ट्रक्टरों के बारे में पूछ रहा है। तकनीकी रूप से कहें तो, function Person(){} सिर्फ एक सामान्य फ़ंक्शन घोषणा है। परंपरा यह है कि कंस्ट्रक्टर के रूप में उपयोग किए जाने वाले फ़ंक्शन के लिए पास्कलकेस का उपयोग किया जाए।

var person = Person() फ़ंक्शन के रूप में Person को इनवोक करता है, और कंस्ट्रक्टर के रूप में नहीं। इस तरह से इनवोक करना एक सामान्य गलती है यदि फ़ंक्शन को कंस्ट्रक्टर के रूप में उपयोग किया जाना है। आम तौर पर, कंस्ट्रक्टर कुछ भी नहीं लौटाता है, इसलिए कंस्ट्रक्टर को एक सामान्य फ़ंक्शन की तरह इनवोक करने से undefined वापस आएगा और वह इंस्टेंस के रूप में इच्छित वैरिएबल को असाइन किया जाएगा।

var person = new Person() new ऑपरेटर का उपयोग करके Person ऑब्जेक्ट का एक इंस्टेंस बनाता है, जो Person.prototype से इनहेरिट होता है। एक विकल्प Object.create का उपयोग करना होगा, जैसे: Object.create(Person.prototype)

function Person(name) { this.name = name; } var person = Person('John'); console.log(person); // undefined console.log(person.name); // Uncaught TypeError: undefined की 'name' प्रॉपर्टी को नहीं पढ़ सकता var person = new Person('John'); console.log(person); // Person { name: "John" } console.log(person.name); // "john"

`.call` और `.apply` में क्या अंतर है?

दोनों .call और .apply का उपयोग फ़ंक्शंस को इनवोक करने के लिए किया जाता है और पहला पैरामीटर फ़ंक्शन के भीतर this के मान के रूप में उपयोग किया जाएगा। हालांकि, .call अगले तर्कों के रूप में कॉमा-सेपरेटेड तर्क लेता है जबकि .apply अगले तर्क के रूप में तर्कों की एक ऐरे लेता है। इसे याद रखने का एक आसान तरीका call के लिए C और कॉमा-सेपरेटेड और apply के लिए A और तर्कों की एक ऐरे है।

function add(a, b) { return a + b; } console.log(add.call(null, 1, 2)); // 3 console.log(add.apply(null, [1, 2])); // 3

`Function.prototype.bind` की व्याख्या करें।

[MDN] से शब्द-दर-शब्द लिया गया है:

bind() विधि एक नया फ़ंक्शन बनाती है, जिसे कॉल करने पर, उसका this कीवर्ड प्रदान किए गए मान पर सेट होता है, जिसमें तर्कों का एक दिया गया क्रम नए फ़ंक्शन को कॉल किए जाने पर प्रदान किए गए किसी भी तर्क से पहले आता है।

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

आप `document.write()` का उपयोग कब करेंगे?

document.write() document.open() द्वारा खोले गए दस्तावेज़ स्ट्रीम में टेक्स्ट की एक स्ट्रिंग लिखता है। जब पृष्ठ लोड होने के बाद document.write() निष्पादित होता है, तो यह document.open को कॉल करेगा जो पूरे दस्तावेज़ (<head> और <body> हटा दिए गए!) को साफ़ कर देता है और दी गई पैरामीटर मान के साथ सामग्री को बदल देता है। इसलिए इसे आमतौर पर खतरनाक और दुरुपयोग के लिए प्रवृत्त माना जाता है।

ऑनलाइन कुछ उत्तर हैं जो बताते हैं कि document.write() का उपयोग एनालिटिक्स कोड में किया जा रहा है या [जब आप ऐसी शैलियों को शामिल करना चाहते हैं जो केवल तभी काम करनी चाहिए जब जावास्क्रिप्ट सक्षम हो]। HTML5 बॉयलरप्लेट में भी इसका उपयोग [स्क्रिप्ट्स को समानांतर में लोड करने और निष्पादन क्रम को संरक्षित करने] के लिए किया जा रहा है! हालांकि, मुझे संदेह है कि वे कारण पुराने हो सकते हैं और आधुनिक समय में, उन्हें document.write() का उपयोग किए बिना प्राप्त किया जा सकता है। कृपया मुझे सही करें यदि मैं इस बारे में गलत हूं।

फीचर डिटेक्शन, फीचर इंफ्रेंस और यूए स्ट्रिंग का उपयोग करने में क्या अंतर है?

फीचर डिटेक्शन

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

if ('geolocation' in navigator) { // navigator.geolocation का उपयोग कर सकते हैं } else { // फीचर की कमी को संभालें }

[मॉडर्निज़र] फीचर डिटेक्शन को संभालने के लिए एक बेहतरीन लाइब्रेरी है।

फीचर इंफ्रेंस

फीचर इंफ्रेंस फीचर डिटेक्शन की तरह ही एक फीचर की जांच करता है, लेकिन एक और फ़ंक्शन का उपयोग करता है क्योंकि यह मानता है कि यह भी मौजूद होगा, उदाहरण के लिए:

if (document.getElementsByTagName) { element = document.getElementById(id); }

यह वास्तव में अनुशंसित नहीं है। फीचर डिटेक्शन अधिक मूर्खतापूर्ण है।

यूए स्ट्रिंग

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

Ajax की यथासंभव विस्तार से व्याख्या करें।

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

XMLHttpRequest API का उपयोग अक्सर एसिंक्रोनस संचार के लिए किया जाता है या आजकल, fetch() API का।

Ajax का उपयोग करने के क्या फायदे और नुकसान हैं?

फायदे

  • बेहतर इंटरएक्टिविटी। सर्वर से नई सामग्री को पूरे पृष्ठ को फिर से लोड करने की आवश्यकता के बिना गतिशील रूप से बदला जा सकता है।
  • सर्वर से कनेक्शन कम करें क्योंकि स्क्रिप्ट और स्टाइलशीट को केवल एक बार अनुरोध करने की आवश्यकता होती है।
  • पृष्ठ पर स्थिति बनाए रखी जा सकती है। जावास्क्रिप्ट वैरिएबल और DOM स्थिति बनी रहेगी क्योंकि मुख्य कंटेनर पृष्ठ फिर से लोड नहीं किया गया था।
  • मूल रूप से एक एसपीए के अधिकांश फायदे।

नुकसान

  • गतिशील वेबपेजों को बुकमार्क करना कठिन होता है।
  • यदि ब्राउज़र में जावास्क्रिप्ट अक्षम कर दिया गया है तो काम नहीं करता है।
  • कुछ वेबक्रॉलर जावास्क्रिप्ट को निष्पादित नहीं करते हैं और जावास्क्रिप्ट द्वारा लोड की गई सामग्री को नहीं देख पाएंगे।
  • Ajax का उपयोग करके डेटा लाने वाले वेबपेजों को DOM को अपडेट करने के लिए क्लाइंट-साइड टेम्प्लेट के साथ लाई गई दूरस्थ डेटा को संयोजित करना होगा। ऐसा होने के लिए, जावास्क्रिप्ट को ब्राउज़र पर पार्स और निष्पादित करना होगा, और निम्न-अंत मोबाइल उपकरणों को इसमें संघर्ष करना पड़ सकता है।
  • मूल रूप से एक एसपीए के अधिकांश नुकसान।

JSONP कैसे काम करता है (और यह वास्तव में Ajax क्यों नहीं है) की व्याख्या करें।

JSONP (JSON with Padding) वेब ब्राउज़रों में क्रॉस-डोमेन नीतियों को बायपास करने के लिए आमतौर पर इस्तेमाल की जाने वाली एक विधि है क्योंकि वर्तमान पृष्ठ से एक क्रॉस-ऑरिजन डोमेन के लिए Ajax अनुरोधों की अनुमति नहीं है।

JSONP एक <script> टैग के माध्यम से और आमतौर पर callback क्वेरी पैरामीटर के साथ एक क्रॉस-ऑरिजन डोमेन के लिए अनुरोध करके काम करता है, उदाहरण के लिए: https://example.com?callback=printData। सर्वर तब डेटा को printData नामक फ़ंक्शन के भीतर लपेटेगा और इसे क्लाइंट को वापस कर देगा।

<script> function printData(data) { console.log(`मेरा नाम ${data.name} है!`); } </script> <script src="[https://example.com?callback=printData](https://example.com?callback=printData)"></script>
printData({ name: 'यांग शुन' });

क्लाइंट के पास अपने वैश्विक दायरे में printData फ़ंक्शन होना चाहिए और फ़ंक्शन को क्लाइंट द्वारा तब निष्पादित किया जाएगा जब क्रॉस-ऑरिजन डोमेन से प्रतिक्रिया प्राप्त होगी।

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

आजकल, [CORS] अनुशंसित दृष्टिकोण है और JSONP को एक हैक के रूप में देखा जाता है।

क्या आपने कभी जावास्क्रिप्ट टेम्प्लेटिंग का उपयोग किया है? यदि हाँ, तो आपने किन पुस्तकालयों का उपयोग किया है?

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

const template = `<div>मेरा नाम है: ${name}</div>`;

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

"होइस्टिंग" की व्याख्या करें।

होइस्टिंग आपके कोड में वैरिएबल घोषणाओं के व्यवहार को समझाने के लिए इस्तेमाल किया जाने वाला एक शब्द है। var कीवर्ड के साथ घोषित या इनिशियलाइज़ किए गए वैरिएबल की घोषणा उनके मॉड्यूल/फ़ंक्शन-स्तर के स्कोप के शीर्ष पर "ले जाया" जाएगा, जिसे हम होइस्टिंग के रूप में संदर्भित करते हैं। हालांकि, केवल घोषणा को होइस्ट किया जाता है, असाइनमेंट (यदि कोई है), वहीं रहेगा जहां वह है।

ध्यान दें कि घोषणा वास्तव में स्थानांतरित नहीं होती है - जावास्क्रिप्ट इंजन संकलन के दौरान घोषणाओं को पार्स करता है और घोषणाओं और उनके स्कोप के बारे में जागरूक हो जाता है। घोषणाओं को उनके स्कोप के शीर्ष पर होइस्ट के रूप में कल्पना करके इस व्यवहार को समझना आसान है। आइए कुछ उदाहरणों के साथ समझाएं।

console.log(foo); // undefined var foo = 1; console.log(foo); // 1

फ़ंक्शन घोषणाओं में बॉडी को होइस्ट किया जाता है जबकि फ़ंक्शन एक्सप्रेशंस (वैरिएबल घोषणाओं के रूप में लिखे गए) में केवल वैरिएबल घोषणा को होइस्ट किया जाता है।

// फ़ंक्शन घोषणा console.log(foo); // [फ़ंक्शन: foo] foo(); // 'FOOOOO' function foo() { console.log('FOOOOO'); } console.log(foo); // [फ़ंक्शन: foo] // फ़ंक्शन एक्सप्रेशन console.log(bar); // undefined bar(); // अनकैच टाइपएरर: bar एक फ़ंक्शन नहीं है var bar = function () { console.log('BARRRR'); }; console.log(bar); // [फ़ंक्शन: bar]

let और const के माध्यम से घोषित वैरिएबल भी होइस्ट किए जाते हैं। हालांकि, var और function के विपरीत, वे इनिशियलाइज़ नहीं होते हैं और घोषणा से पहले उन्हें एक्सेस करने से रेफरेंसएरर अपवाद होगा। ब्लॉक की शुरुआत से लेकर घोषणा के संसाधित होने तक वैरिएबल "टेम्पोरल डेड ज़ोन" में होता है।

x; // undefined y; // रेफरेंस एरर: y परिभाषित नहीं है var x = 'स्थानीय'; let y = 'स्थानीय';

इवेंट बबलिंग का वर्णन करें।

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

एक "विशेषता" और एक "गुण" के बीच क्या अंतर है?

विशेषताएं HTML मार्कअप पर परिभाषित होती हैं लेकिन गुण DOM पर परिभाषित होते हैं। अंतर को स्पष्ट करने के लिए, कल्पना कीजिए कि हमारे HTML में यह टेक्स्ट फ़ील्ड है: <input type="text" value="Hello">

const input = document.querySelector('input'); console.log(input.getAttribute('value')); // Hello console.log(input.value); // Hello

लेकिन टेक्स्ट फ़ील्ड के मान को "World!" जोड़कर बदलने के बाद, यह बन जाता है:

console.log(input.getAttribute('value')); // Hello console.log(input.value); // Hello World!

अंतर्निहित जावास्क्रिप्ट ऑब्जेक्ट्स का विस्तार करना एक अच्छा विचार क्यों नहीं है?

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

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

दस्तावेज़ `load` इवेंट और दस्तावेज़ `DOMContentLoaded` इवेंट के बीच क्या अंतर है?

DOMContentLoaded इवेंट तब फायर होता है जब प्रारंभिक HTML दस्तावेज़ पूरी तरह से लोड और पार्स हो जाता है, स्टाइलशीट, छवियों और सबफ्रेम के लोड होने का इंतजार किए बिना।

window का load इवेंट DOM और सभी निर्भर संसाधनों और संपत्तियों के लोड होने के बाद ही फायर होता है।

`==` और `===` में क्या अंतर है?

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

1 == '1'; // true 1 == [1]; // true 1 == true; // true 0 == ''; // true 0 == '0'; // true 0 == false; // true

मेरी सलाह है कि == ऑपरेटर का उपयोग कभी न करें, सिवाय null या undefined के खिलाफ तुलना करते समय सुविधा के लिए, जहां a == null यदि a null या undefined है तो true लौटाएगा।

var a = null; console.log(a == null); // true console.log(a == undefined); // true

जावास्क्रिप्ट के संबंध में समान-मूल नीति की व्याख्या करें।

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

इसे काम करें:

duplicate([1, 2, 3, 4, 5]); // [1,2,3,4,5,1,2,3,4,5]
function duplicate(arr) { return arr.concat(arr); } duplicate([1, 2, 3, 4, 5]); // [1,2,3,4,5,1,2,3,4,5]

या ES6 के साथ:

const duplicate = (arr) => [...arr, ...arr]; duplicate([1, 2, 3, 4, 5]); // [1,2,3,4,5,1,2,3,4,5]

यह एक टर्नरी एक्सप्रेशन क्यों कहलाता है, 'टर्नरी' शब्द क्या दर्शाता है?

टर्नरी का अर्थ तीन होता है, और एक टर्नरी एक्सप्रेशन तीन ऑपरेंड स्वीकार करता है: परीक्षण स्थिति, 'तब' एक्सप्रेशन और 'अन्यथा' एक्सप्रेशन। टर्नरी एक्सप्रेशन जावास्क्रिप्ट के लिए विशिष्ट नहीं हैं और मुझे यकीन नहीं है कि यह इस सूची में क्यों है।

`"use strict";` क्या है? इसका उपयोग करने के क्या फायदे और नुकसान हैं?

'use strict' पूरे स्क्रिप्ट या व्यक्तिगत फ़ंक्शन में सख्त मोड को सक्षम करने के लिए उपयोग किया जाने वाला एक कथन है। सख्त मोड जावास्क्रिप्ट के एक प्रतिबंधित संस्करण को चुनने का एक तरीका है।

फायदे:

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

नुकसान:

  • कई लापता सुविधाएँ जिनका कुछ डेवलपर्स उपयोग करते होंगे।
  • function.caller और function.arguments तक कोई और पहुंच नहीं।
  • विभिन्न सख्त मोड में लिखी गई स्क्रिप्ट का संयोजन समस्याएँ पैदा कर सकता है।

कुल मिलाकर, मुझे लगता है कि फायदे नुकसान से अधिक हैं, और मुझे कभी भी उन सुविधाओं पर निर्भर नहीं रहना पड़ा है जिन्हें सख्त मोड ब्लॉक करता है। मैं सख्त मोड का उपयोग करने की सलाह दूंगा।

एक फॉर लूप बनाएँ जो `100` तक दोहराता है, जबकि `3` के गुणकों पर **"fizz"**, `5` के गुणकों पर **"buzz"** और `3` और `5` दोनों के गुणकों पर **"fizzbuzz"** आउटपुट करता है।

[पॉल आयरिश] द्वारा फ़िज़बज़ के इस संस्करण को देखें।

for (let i = 1; i <= 100; i++) { let f = i % 3 == 0, b = i % 5 == 0; console.log(f ? (b ? 'FizzBuzz' : 'Fizz') : b ? 'Buzz' : i); }

हालांकि, मैं आपको साक्षात्कार के दौरान उपरोक्त लिखने की सलाह नहीं दूंगा। बस लंबे लेकिन स्पष्ट दृष्टिकोण पर टिके रहें। फ़िज़बज़ के अधिक सनकी संस्करणों के लिए, नीचे दिए गए संदर्भ लिंक को देखें।

किसी वेबसाइट के ग्लोबल स्कोप को वैसे ही छोड़ना और उसे कभी न छूना, आम तौर पर एक अच्छा विचार क्यों है?

हर स्क्रिप्ट को ग्लोबल स्कोप तक पहुंच होती है, और यदि हर कोई अपने वैरिएबल को परिभाषित करने के लिए ग्लोबल नेमस्पेस का उपयोग करता है, तो टकराव होने की संभावना है। अपने वैरिएबल को एक स्थानीय नेमस्पेस के भीतर इनकैप्सुलेट करने के लिए मॉड्यूल पैटर्न (IIFEs) का उपयोग करें।

`load` इवेंट जैसी किसी चीज़ का उपयोग क्यों करेंगे? क्या इस इवेंट के नुकसान हैं? क्या आप कोई विकल्प जानते हैं, और आप उनका उपयोग क्यों करेंगे?

load इवेंट दस्तावेज़ लोडिंग प्रक्रिया के अंत में फायर होता है। इस बिंदु पर, दस्तावेज़ में सभी ऑब्जेक्ट DOM में होते हैं, और सभी इमेज, स्क्रिप्ट, लिंक और सब-फ़्रेम लोड होना समाप्त कर चुके होते हैं।

DOM इवेंट DOMContentLoaded पृष्ठ के लिए DOM के निर्मित होने के बाद फायर होगा, लेकिन अन्य संसाधनों के लोड होने का इंतजार नहीं करेगा। कुछ मामलों में यह बेहतर है जब आपको इनिशियलाइज़ेशन से पहले पूरे पृष्ठ को लोड करने की आवश्यकता नहीं होती है।

बताएं कि सिंगल पेज ऐप क्या है और इसे SEO-फ्रेंडली कैसे बनाया जाए।

नीचे दिए गए शानदार [ग्रैब फ्रंट एंड गाइड] से लिया गया है, जो संयोग से, मेरे द्वारा लिखा गया है!

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

हालांकि, आधुनिक SPAs में, क्लाइंट-साइड रेंडरिंग का उपयोग किया जाता है। ब्राउज़र सर्वर से प्रारंभिक पृष्ठ लोड करता है, साथ ही पूरे ऐप के लिए आवश्यक स्क्रिप्ट (फ्रेमवर्क, लाइब्रेरी, ऐप कोड) और स्टाइलशीट भी लोड करता है। जब उपयोगकर्ता अन्य पृष्ठों पर नेविगेट करता है, तो पृष्ठ रीफ्रेश ट्रिगर नहीं होता है। पृष्ठ का URL [HTML5 हिस्ट्री API] के माध्यम से अपडेट किया जाता है। नए पृष्ठ के लिए आवश्यक नया डेटा, आमतौर पर JSON प्रारूप में, ब्राउज़र द्वारा सर्वर पर [AJAX] अनुरोधों के माध्यम से पुनर्प्राप्त किया जाता है। SPA तब JavaScript के माध्यम से डेटा के साथ पृष्ठ को गतिशील रूप से अपडेट करता है, जिसे उसने प्रारंभिक पृष्ठ लोड में पहले ही डाउनलोड कर लिया है। यह मॉडल इस बात के समान है कि देशी मोबाइल ऐप कैसे काम करते हैं।

लाभ:

  • ऐप अधिक उत्तरदायी महसूस करता है और उपयोगकर्ताओं को पूर्ण-पृष्ठ रीफ्रेश के कारण पृष्ठ नेविगेशन के बीच फ्लैश नहीं दिखता है।
  • सर्वर पर कम HTTP अनुरोध किए जाते हैं, क्योंकि प्रत्येक पृष्ठ लोड के लिए समान परिसंपत्तियों को फिर से डाउनलोड नहीं करना पड़ता है।
  • क्लाइंट और सर्वर के बीच चिंताओं का स्पष्ट पृथक्करण; आप सर्वर कोड को संशोधित किए बिना विभिन्न प्लेटफार्मों (जैसे मोबाइल, चैटबॉट, स्मार्ट घड़ियां) के लिए आसानी से नए क्लाइंट बना सकते हैं। आप क्लाइंट और सर्वर पर प्रौद्योगिकी स्टैक को भी स्वतंत्र रूप से संशोधित कर सकते हैं, जब तक कि API अनुबंध नहीं टूटता है।

नुकसान:

  • कई पृष्ठों के लिए आवश्यक फ्रेमवर्क, ऐप कोड और परिसंपत्तियों को लोड करने के कारण भारी प्रारंभिक पृष्ठ लोड।
  • आपके सर्वर पर एक अतिरिक्त कदम उठाना होगा जो इसे सभी अनुरोधों को एक ही एंट्री पॉइंट पर रूट करने और क्लाइंट-साइड रूटिंग को वहां से संभालने की अनुमति देने के लिए कॉन्फ़िगर करना है।
  • SPAs सामग्री को रेंडर करने के लिए JavaScript पर निर्भर हैं, लेकिन सभी सर्च इंजन क्रॉलिंग के दौरान JavaScript को निष्पादित नहीं करते हैं, और वे आपके पृष्ठ पर खाली सामग्री देख सकते हैं। यह अनजाने में आपके ऐप के सर्च इंजन ऑप्टिमाइज़ेशन (SEO) को नुकसान पहुंचाता है। हालांकि, अधिकांश समय, जब आप ऐप बना रहे होते हैं, तो SEO सबसे महत्वपूर्ण कारक नहीं होता है, क्योंकि सभी सामग्री को सर्च इंजन द्वारा अनुक्रमित करने की आवश्यकता नहीं होती है। इसे दूर करने के लिए, आप या तो अपने ऐप को सर्वर-साइड रेंडर कर सकते हैं या [प्रिरेंडर] जैसी सेवाओं का उपयोग कर सकते हैं ताकि "अपने जावास्क्रिप्ट को ब्राउज़र में रेंडर किया जा सके, स्थिर HTML को सहेजा जा सके, और क्रॉलर को वापस किया जा सके"।

प्रॉमिस और/या उनके पॉलीफ़िल के साथ आपके अनुभव की सीमा क्या है?

इसका कार्यसाधक ज्ञान है। एक प्रॉमिस एक ऑब्जेक्ट है जो भविष्य में किसी समय एक ही मान का उत्पादन कर सकता है: या तो एक हल किया गया मान या एक कारण कि यह हल नहीं हुआ है (उदाहरण के लिए, एक नेटवर्क त्रुटि हुई)। एक प्रॉमिस 3 संभावित अवस्थाओं में से एक में हो सकता है: पूरा किया गया, अस्वीकृत, या लंबित। प्रॉमिस उपयोगकर्ता हल किए गए मान या अस्वीकृति के कारण को संभालने के लिए कॉलबैक संलग्न कर सकते हैं।

कुछ सामान्य पॉलीफ़िल $.deferred, Q और Bluebird हैं लेकिन वे सभी विनिर्देशों का पालन नहीं करते हैं। ES2015 आउट ऑफ द बॉक्स प्रॉमिस का समर्थन करता है और आजकल पॉलीफ़िल की आमतौर पर आवश्यकता नहीं होती है।

कॉलबैक के बजाय प्रॉमिस का उपयोग करने के क्या फायदे और नुकसान हैं?

फायदे

  • कॉलबैक हेल से बचें जो अपठनीय हो सकता है।
  • .then() के साथ पठनीय अनुक्रमिक अतुल्यकालिक कोड लिखना आसान बनाता है।
  • Promise.all() के साथ समानांतर अतुल्यकालिक कोड लिखना आसान बनाता है।
  • प्रॉमिस के साथ, कॉलबैक-ओनली कोडिंग में मौजूद ये परिदृश्य नहीं होंगे:
    • कॉलबैक को बहुत जल्दी कॉल करें
    • कॉलबैक को बहुत देर से (या कभी नहीं) कॉल करें
    • कॉलबैक को बहुत कम या बहुत बार कॉल करें
    • किसी भी आवश्यक वातावरण/पैरामीटर को पास करने में विफल रहें
    • होने वाली किसी भी त्रुटि/अपवाद को निगल लें

नुकसान

  • थोड़ा अधिक जटिल कोड (विवादास्पद)।
  • पुराने ब्राउज़रों में जहां ES2015 समर्थित नहीं है, आपको इसका उपयोग करने के लिए एक पॉलीफ़िल लोड करने की आवश्यकता है।

जावास्क्रिप्ट में संकलित होने वाली भाषा में जावास्क्रिप्ट कोड लिखने के क्या फायदे/नुकसान हैं?

जावास्क्रिप्ट में संकलित होने वाली भाषाओं के कुछ उदाहरणों में CoffeeScript, Elm, ClojureScript, PureScript और TypeScript शामिल हैं।

फायदे:

  • जावास्क्रिप्ट में कुछ लंबे समय से चली आ रही समस्याओं को ठीक करता है और जावास्क्रिप्ट एंटी-पैटर्न को हतोत्साहित करता है।
  • आपको छोटा कोड लिखने में सक्षम बनाता है, जावास्क्रिप्ट के शीर्ष पर कुछ सिंटैक्टिक शुगर प्रदान करके, जिसकी मुझे लगता है कि ES5 में कमी है, लेकिन ES2015 शानदार है।
  • बड़े प्रोजेक्ट के लिए स्टैटिक प्रकार बहुत अच्छे हैं (टाइपस्क्रिप्ट के मामले में) जिन्हें समय के साथ बनाए रखने की आवश्यकता है।

नुकसान:

  • एक बिल्ड/संकलन प्रक्रिया की आवश्यकता है क्योंकि ब्राउज़र केवल जावास्क्रिप्ट चलाते हैं और आपके कोड को ब्राउज़र में परोसे जाने से पहले जावास्क्रिप्ट में संकलित करने की आवश्यकता होगी।
  • डिबगिंग एक दर्द हो सकता है यदि आपके स्रोत मानचित्र आपके पूर्व-संकलित स्रोत में अच्छी तरह से मैप नहीं करते हैं।
  • अधिकांश डेवलपर्स इन भाषाओं से परिचित नहीं हैं और उन्हें सीखने की आवश्यकता होगी। यदि आप इसे अपने प्रोजेक्ट के लिए उपयोग करते हैं तो आपकी टीम के लिए एक रैंप अप लागत शामिल है।
  • छोटा समुदाय (भाषा के आधार पर), जिसका अर्थ है कि संसाधन, ट्यूटोरियल, लाइब्रेरी और टूलिंग खोजना कठिन होगा।
  • IDE/संपादक समर्थन की कमी हो सकती है।
  • ये भाषाएँ हमेशा नवीनतम जावास्क्रिप्ट मानक से पीछे रहेंगी।
  • डेवलपर्स को इस बात से अवगत होना चाहिए कि उनका कोड किसमें संकलित किया जा रहा है - क्योंकि वही वास्तव में चल रहा होगा, और अंत में वही मायने रखता है।

व्यावहारिक रूप से, ES2015 ने जावास्क्रिप्ट में बहुत सुधार किया है और इसे लिखना बहुत आसान बना दिया है। मुझे आजकल CoffeeScript की आवश्यकता नहीं दिखती है।

आप जावास्क्रिप्ट कोड को डिबग करने के लिए किन टूल और तकनीकों का उपयोग करते हैं?

  • रिएक्ट और रेडक्स
    • [रिएक्ट देवटूल्स]
    • [रेडक्स देवटूल्स]
  • व्यू
    • [व्यू देवटूल्स]
  • जावास्क्रिप्ट
    • [क्रोम देवटूल्स]
    • debugger स्टेटमेंट
    • गुड ओल्ड console.log डिबगिंग

आप ऑब्जेक्ट प्रॉपर्टीज और एरे आइटम्स पर इटरेट करने के लिए किन भाषा कंस्ट्रक्शन का उपयोग करते हैं?

ऑब्जेक्ट्स के लिए:

  • for-in लूप्स - for (var property in obj) { console.log(property); }। हालांकि, यह इसकी इनहेरिटेड प्रॉपर्टीज पर भी इटरेट करेगा, और आप इसका उपयोग करने से पहले एक obj.hasOwnProperty(property) चेक जोड़ेंगे।
  • Object.keys() - Object.keys(obj).forEach(function (property) { ... })Object.keys() एक स्टैटिक मेथड है जो आपके द्वारा इसे पास किए गए ऑब्जेक्ट की सभी इन्यूमरेबल प्रॉपर्टीज को सूचीबद्ध करेगा।
  • Object.getOwnPropertyNames() - Object.getOwnPropertyNames(obj).forEach(function (property) { ... })Object.getOwnPropertyNames() एक स्टैटिक मेथड है जो आपके द्वारा इसे पास किए गए ऑब्जेक्ट की सभी इन्यूमरेबल और नॉन-इन्यूमरेबल प्रॉपर्टीज को सूचीबद्ध करेगा।

एरे के लिए:

  • for लूप्स - for (var i = 0; i < arr.length; i++)। यहां आम गलती यह है कि var फंक्शन स्कोप में है न कि ब्लॉक स्कोप में और ज्यादातर समय आप ब्लॉक स्कोपेड इटरेटर वैरिएबल चाहते होंगे। ES2015 let को पेश करता है जिसमें ब्लॉक स्कोप होता है और इसके बजाय इसका उपयोग करने की सिफारिश की जाती है। तो यह बन जाता है: for (let i = 0; i < arr.length; i++)
  • forEach - arr.forEach(function (el, index) { ... })। यह कंस्ट्रक्ट कभी-कभी अधिक सुविधाजनक हो सकता है क्योंकि यदि आपको केवल एरे एलिमेंट्स की आवश्यकता है तो आपको index का उपयोग करने की आवश्यकता नहीं है। every और some मेथड भी हैं जो आपको इटरेटर को जल्दी समाप्त करने की अनुमति देंगे।
  • for-of लूप्स - for (let elem of arr) { ... }। ES6 एक नया लूप, for-of लूप पेश करता है, जो आपको String, Array, Map, Set, आदि जैसे इटरेबल प्रोटोकॉल के अनुरूप ऑब्जेक्ट्स पर लूप करने की अनुमति देता है। यह for लूप और forEach() मेथड के फायदों को जोड़ता है। for लूप का फायदा यह है कि आप इससे ब्रेक कर सकते हैं, और forEach() का फायदा यह है कि यह for लूप की तुलना में अधिक संक्षिप्त है क्योंकि आपको काउंटर वैरिएबल की आवश्यकता नहीं है। for-of लूप के साथ, आपको लूप से ब्रेक करने की क्षमता और अधिक संक्षिप्त सिंटैक्स दोनों मिलते हैं।

अधिकांश समय, मैं .forEach मेथड को प्राथमिकता दूंगा, लेकिन यह वास्तव में इस बात पर निर्भर करता है कि आप क्या करने की कोशिश कर रहे हैं। ES6 से पहले, जब हमें break का उपयोग करके लूप को समय से पहले समाप्त करने की आवश्यकता होती थी, तो हम for लूप का उपयोग करते थे। लेकिन अब ES6 के साथ, हम for-of लूप के साथ ऐसा कर सकते हैं। जब मुझे और भी अधिक लचीलेपन की आवश्यकता होती है, जैसे प्रति लूप में इटरेटर को एक से अधिक बार बढ़ाना, तो मैं for लूप का उपयोग करूंगा।

इसके अलावा, for-of लूप का उपयोग करते समय, यदि आपको प्रत्येक एरे एलिमेंट के इंडेक्स और वैल्यू दोनों तक पहुंचने की आवश्यकता है, तो आप ES6 एरे entries() मेथड और डीस्ट्रक्चरिंग के साथ ऐसा कर सकते हैं:

const arr = ['a', 'b', 'c']; for (let [index, elem] of arr.entries()) { console.log(index, ': ', elem); }

म्यूटेबल और इम्यूटेबल ऑब्जेक्ट्स के बीच अंतर बताएं।

इम्यूटेबिलिटी कार्यात्मक प्रोग्रामिंग में एक मुख्य सिद्धांत है, और ऑब्जेक्ट-ओरिएंटेड प्रोग्राम्स को भी बहुत कुछ प्रदान करती है। एक म्यूटेबल ऑब्जेक्ट एक ऐसा ऑब्जेक्ट है जिसकी स्थिति को उसके बनाए जाने के बाद संशोधित किया जा सकता है। एक इम्यूटेबल ऑब्जेक्ट एक ऐसा ऑब्जेक्ट है जिसकी स्थिति को उसके बनाए जाने के बाद संशोधित नहीं किया जा सकता है।

जावास्क्रिप्ट में इम्यूटेबल ऑब्जेक्ट का उदाहरण क्या है?

जावास्क्रिप्ट में, कुछ बिल्ट-इन प्रकार (संख्याएं, स्ट्रिंग्स) इम्यूटेबल होते हैं, लेकिन कस्टम ऑब्जेक्ट्स आम तौर पर म्यूटेबल होते हैं।

कुछ बिल्ट-इन इम्यूटेबल जावास्क्रिप्ट ऑब्जेक्ट्स Math, Date हैं।

साधारण जावास्क्रिप्ट ऑब्जेक्ट्स पर इम्यूटेबिलिटी जोड़ने/अनुकरण करने के कुछ तरीके यहां दिए गए हैं।

ऑब्जेक्ट कॉन्स्टेंट प्रॉपर्टीज

writable: false और configurable: false को मिलाकर, आप अनिवार्य रूप से एक कॉन्स्टेंट (बदला नहीं जा सकता, फिर से परिभाषित या हटाया नहीं जा सकता) को एक ऑब्जेक्ट प्रॉपर्टी के रूप में बना सकते हैं, जैसे:

let myObject = {}; Object.defineProperty(myObject, 'number', { value: 42, writable: false, configurable: false, }); console.log(myObject.number); // 42 myObject.number = 43; console.log(myObject.number); // 42

एक्सटेंशन को रोकें

यदि आप किसी ऑब्जेक्ट को नई प्रॉपर्टीज जोड़ने से रोकना चाहते हैं, लेकिन ऑब्जेक्ट की बाकी प्रॉपर्टीज को वैसे ही छोड़ना चाहते हैं, तो Object.preventExtensions(...) को कॉल करें:

var myObject = { a: 2, }; Object.preventExtensions(myObject); myObject.b = 3; myObject.b; // undefined

नॉन-स्ट्रिक्ट मोड में, b का निर्माण चुपचाप विफल हो जाता है। सख्त मोड में, यह एक TypeError फेंकता है।

सील

Object.seal() एक "सील्ड" ऑब्जेक्ट बनाता है, जिसका अर्थ है कि यह एक मौजूदा ऑब्जेक्ट लेता है और अनिवार्य रूप से उस पर Object.preventExtensions() को कॉल करता है, लेकिन इसकी सभी मौजूदा प्रॉपर्टीज को configurable: false के रूप में भी चिह्नित करता है।

तो, न केवल आप कोई और प्रॉपर्टी नहीं जोड़ सकते हैं, बल्कि आप किसी भी मौजूदा प्रॉपर्टी को फिर से कॉन्फ़िगर या हटा भी नहीं सकते हैं (हालांकि आप अभी भी उनके मानों को संशोधित कर सकते हैं)।

फ्रीज

Object.freeze() एक फ़्रोजन ऑब्जेक्ट बनाता है, जिसका अर्थ है कि यह एक मौजूदा ऑब्जेक्ट लेता है और अनिवार्य रूप से उस पर Object.seal() को कॉल करता है, लेकिन यह सभी "डेटा एक्सेसर्स" प्रॉपर्टीज को writable:false के रूप में भी चिह्नित करता है, ताकि उनके मानों को बदला न जा सके।

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

var immutable = Object.freeze({});

किसी ऑब्जेक्ट को फ्रीज करने से ऑब्जेक्ट में नई प्रॉपर्टीज जोड़ने की अनुमति नहीं मिलती है और मौजूदा प्रॉपर्टीज को हटाने या बदलने से रोका जाता है। Object.freeze() ऑब्जेक्ट की इन्यूमरेबिलिटी, कॉन्फ़िगरेबिलिटी, राइटेबिलिटी और प्रोटोटाइप को संरक्षित करता है। यह पास किए गए ऑब्जेक्ट को वापस करता है और एक फ़्रोजन कॉपी नहीं बनाता है।

इम्यूटेबिलिटी के क्या फायदे और नुकसान हैं?

फायदे

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

नुकसान

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

आप अपने स्वयं के कोड में इम्यूटेबिलिटी कैसे प्राप्त कर सकते हैं?

वैकल्पिक रूप से const घोषणाओं का उपयोग करना है जो निर्माण के लिए ऊपर वर्णित तकनीकों के साथ संयुक्त हैं। ऑब्जेक्ट्स को "म्यूटेट" करने के लिए, स्प्रेड ऑपरेटर, Object.assign, Array.concat() आदि का उपयोग करें, ताकि मूल ऑब्जेक्ट को म्यूटेट करने के बजाय नए ऑब्जेक्ट बनाए जा सकें।

उदाहरण:

// एरे उदाहरण const arr = [1, 2, 3]; const newArr = [...arr, 4]; // [1, 2, 3, 4] // ऑब्जेक्ट उदाहरण const human = Object.freeze({ race: 'human' }); const john = { ...human, name: 'John' }; // {race: "human", name: "John"} const alienJohn = { ...john, race: 'alien' }; // {race: "alien", name: "John"}

सिंक्रोनस और एसिंक्रोनस फ़ंक्शन के बीच अंतर बताएं।

सिंक्रोनस फ़ंक्शन ब्लॉकिंग होते हैं जबकि एसिंक्रोनस फ़ंक्शन नहीं होते हैं। सिंक्रोनस फ़ंक्शन में, कथन अगले कथन के चलने से पहले पूरे हो जाते हैं। इस मामले में, प्रोग्राम का मूल्यांकन कथनों के ठीक क्रम में किया जाता है और यदि एक कथन को बहुत लंबा समय लगता है तो प्रोग्राम का निष्पादन रोक दिया जाता है।

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

इवेंट लूप क्या है? कॉल स्टैक और टास्क क्यू के बीच क्या अंतर है?

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

यदि आपने अभी तक इवेंट लूप पर फिलिप रॉबर्ट की बात नहीं देखी है, तो आपको देखनी चाहिए। यह जावास्क्रिप्ट पर सबसे अधिक देखे जाने वाले वीडियो में से एक है।

`function foo() {}` और `var foo = function() {}` के बीच `foo` के उपयोग में अंतर बताएं

पूर्व एक फ़ंक्शन घोषणा है जबकि बाद वाला एक फ़ंक्शन एक्सप्रेशन है। मुख्य अंतर यह है कि फ़ंक्शन घोषणाओं का उनका शरीर उठाया जाता है लेकिन फ़ंक्शन एक्सप्रेशन के शरीर नहीं होते हैं (उनके पास वैरिएबल के समान होस्टिंग व्यवहार होता है)। होस्टिंग पर अधिक स्पष्टीकरण के लिए, ऊपर दिए गए प्रश्न को देखें होस्टिंग पर। यदि आप किसी फ़ंक्शन एक्सप्रेशन को परिभाषित करने से पहले इनवोक करने का प्रयास करते हैं, तो आपको Uncaught TypeError: XXX is not a function त्रुटि मिलेगी।

फ़ंक्शन घोषणा

foo(); // 'FOOOOO' function foo() { console.log('FOOOOO'); }

फ़ंक्शन एक्सप्रेशन

foo(); // Uncaught TypeError: foo is not a function var foo = function () { console.log('FOOOOO'); };

`let`, `var` या `const` का उपयोग करके बनाए गए वैरिएबल के बीच क्या अंतर हैं?

var कीवर्ड का उपयोग करके घोषित वैरिएबल उस फ़ंक्शन के लिए स्कोप किए जाते हैं जिसमें वे बनाए जाते हैं, या यदि किसी फ़ंक्शन के बाहर बनाए जाते हैं, तो वैश्विक ऑब्जेक्ट के लिए। let और const ब्लॉक स्कोप किए गए होते हैं, जिसका अर्थ है कि वे केवल घुंघराले कोष्ठकों के निकटतम सेट (फ़ंक्शन, इफ-एल्स ब्लॉक, या फॉर-लूप) के भीतर ही पहुंच योग्य होते हैं।

function foo() { // सभी वैरिएबल फ़ंक्शन के भीतर पहुंच योग्य हैं। var bar = 'bar'; let baz = 'baz'; const qux = 'qux'; console.log(bar); // bar console.log(baz); // baz console.log(qux); // qux } console.log(bar); // ReferenceError: bar is not defined console.log(baz); // ReferenceError: baz is not defined console.log(qux); // ReferenceError: qux is not defined
if (true) { var bar = 'bar'; let baz = 'baz'; const qux = 'qux'; } // var घोषित वैरिएबल फ़ंक्शन स्कोप में कहीं भी पहुंच योग्य हैं। console.log(bar); // bar // let और const परिभाषित वैरिएबल उस ब्लॉक के बाहर पहुंच योग्य नहीं हैं जिसमें वे परिभाषित किए गए थे। console.log(baz); // ReferenceError: baz is not defined console.log(qux); // ReferenceError: qux is not defined

var वैरिएबल को होस्ट करने की अनुमति देता है, जिसका अर्थ है कि उन्हें घोषित करने से पहले कोड में संदर्भित किया जा सकता है। let और const इसकी अनुमति नहीं देंगे, इसके बजाय एक त्रुटि फेंक देंगे।

console.log(foo); // undefined var foo = 'foo'; console.log(baz); // ReferenceError: can't access lexical declaration 'baz' before initialization let baz = 'baz'; console.log(bar); // ReferenceError: can't access lexical declaration 'bar' before initialization const bar = 'bar';

var के साथ एक वैरिएबल को फिर से घोषित करने से कोई त्रुटि नहीं होगी, लेकिन let और const करेंगे।

var foo = 'foo'; var foo = 'bar'; console.log(foo); // "bar" let baz = 'baz'; let baz = 'qux'; // Uncaught SyntaxError: Identifier 'baz' has already been declared

let और const इस बात में भिन्न हैं कि let वैरिएबल के मान को फिर से असाइन करने की अनुमति देता है जबकि const नहीं।

// यह ठीक है। let foo = 'foo'; foo = 'bar'; // यह एक अपवाद का कारण बनता है। const baz = 'baz'; baz = 'qux';

ES6 क्लास और ES5 फ़ंक्शन कंस्ट्रक्टर के बीच क्या अंतर हैं?

आइए पहले प्रत्येक का उदाहरण देखें:

// ES5 फ़ंक्शन कंस्ट्रक्टर function Person(name) { this.name = name; } // ES6 क्लास class Person { constructor(name) { this.name = name; } }

सरल कंस्ट्रक्टरों के लिए, वे काफी समान दिखते हैं।

कंस्ट्रक्टर में मुख्य अंतर इनहेरिटेंस का उपयोग करते समय आता है। यदि हम एक Student क्लास बनाना चाहते हैं जो Person का सबक्लास है और एक studentId फ़ील्ड जोड़ना चाहते हैं, तो हमें उपरोक्त के अतिरिक्त यह करना होगा।

// ES5 फ़ंक्शन कंस्ट्रक्टर function Student(name, studentId) { // सुपरक्लास-व्युत्पन्न सदस्यों को इनिशियलाइज़ करने के लिए सुपरक्लास के कंस्ट्रक्टर को कॉल करें। Person.call(this, name); // सबक्लास के अपने सदस्यों को इनिशियलाइज़ करें। this.studentId = studentId; } Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; // ES6 क्लास class Student extends Person { constructor(name, studentId) { super(name); this.studentId = studentId; } }

ES5 में इनहेरिटेंस का उपयोग करना बहुत अधिक वर्बोस है और ES6 संस्करण को समझना और याद रखना आसान है।

क्या आप नए एरो => फ़ंक्शन सिंटैक्स के लिए एक उपयोग मामला पेश कर सकते हैं? यह नया सिंटैक्स अन्य फ़ंक्शन से कैसे भिन्न है?

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

कंस्ट्रक्टर में किसी विधि के लिए एरो सिंटैक्स का उपयोग करने का क्या फायदा है?

कंस्ट्रक्टर के अंदर एक विधि के रूप में एरो फ़ंक्शन का उपयोग करने का मुख्य लाभ यह है कि फ़ंक्शन निर्माण के समय this का मान सेट हो जाता है और उसके बाद बदल नहीं सकता है। तो, जब कंस्ट्रक्टर का उपयोग एक नया ऑब्जेक्ट बनाने के लिए किया जाता है, तो this हमेशा उस ऑब्जेक्ट को संदर्भित करेगा। उदाहरण के लिए, मान लीजिए हमारे पास एक Person कंस्ट्रक्टर है जो पहले नाम को एक तर्क के रूप में लेता है और उस नाम को console.log करने के लिए दो विधियां हैं, एक नियमित फ़ंक्शन के रूप में और एक एरो फ़ंक्शन के रूप में:

const Person = function (firstName) { this.firstName = firstName; this.sayName1 = function () { console.log(this.firstName); }; this.sayName2 = () => { console.log(this.firstName); }; }; const john = new Person('John'); const dave = new Person('Dave'); john.sayName1(); // John john.sayName2(); // John // नियमित फ़ंक्शन का 'this' मान बदला जा सकता है, लेकिन एरो फ़ंक्शन का नहीं john.sayName1.call(dave); // Dave (क्योंकि "this" अब डेव ऑब्जेक्ट है) john.sayName2.call(dave); // John john.sayName1.apply(dave); // Dave (क्योंकि 'this' अब डेव ऑब्जेक्ट है) john.sayName2.apply(dave); // John john.sayName1.bind(dave)(); // Dave (क्योंकि 'this' अब डेव ऑब्जेक्ट है) john.sayName2.bind(dave)(); // John var sayNameFromWindow1 = john.sayName1; sayNameFromWindow1(); // undefined (क्योंकि 'this' अब विंडो ऑब्जेक्ट है) var sayNameFromWindow2 = john.sayName2; sayNameFromWindow2(); // John

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

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

उच्च-क्रम फ़ंक्शन की परिभाषा क्या है?

एक उच्च-क्रम फ़ंक्शन कोई भी फ़ंक्शन है जो एक या एक से अधिक फ़ंक्शन को तर्क के रूप में लेता है, जिसका उपयोग वह कुछ डेटा पर काम करने के लिए करता है, और/या परिणाम के रूप में एक फ़ंक्शन लौटाता है। उच्च-क्रम फ़ंक्शन का उद्देश्य किसी ऐसे ऑपरेशन को अमूर्त करना है जिसे बार-बार किया जाता है। इसका क्लासिक उदाहरण map है, जो एक एरे और एक फ़ंक्शन को तर्क के रूप में लेता है। map तब इस फ़ंक्शन का उपयोग एरे में प्रत्येक आइटम को बदलने के लिए करता है, परिवर्तित डेटा के साथ एक नया एरे लौटाता है। जावास्क्रिप्ट में अन्य लोकप्रिय उदाहरण forEach, filter और reduce हैं। एक उच्च-क्रम फ़ंक्शन को केवल एरे में हेरफेर करने की आवश्यकता नहीं है क्योंकि दूसरे फ़ंक्शन से एक फ़ंक्शन लौटने के लिए कई उपयोग के मामले हैं। Function.prototype.bind जावास्क्रिप्ट में ऐसा ही एक उदाहरण है।

मैप

मान लीजिए हमारे पास नामों का एक एरे है जिसे हमें प्रत्येक स्ट्रिंग को अपरकेस में बदलना होगा।

const names = ['irish', 'daisy', 'anna'];

अनिवार्य तरीका इस प्रकार होगा:

const transformNamesToUppercase = function (names) { const results = []; for (let i = 0; i < names.length; i++) { results.push(names[i].toUpperCase()); } return results; }; transformNamesToUppercase(names); // ['IRISH', 'DAISY', 'ANNA']

.map(transformerFn) का उपयोग करने से कोड छोटा और अधिक घोषणात्मक हो जाता है।

const transformNamesToUppercase = function (names) { return names.map((name) => name.toUpperCase()); }; transformNamesToUppercase(names); // ['IRISH', 'DAISY', 'ANNA']

क्या आप किसी ऑब्जेक्ट या एरे को डीस्ट्रक्चरिंग करने का उदाहरण दे सकते हैं?

डीस्ट्रक्चरिंग ES6 में उपलब्ध एक एक्सप्रेशन है जो ऑब्जेक्ट्स या एरे के मानों को निकालने और उन्हें अलग-अलग वैरिएबल में रखने का एक संक्षिप्त और सुविधाजनक तरीका सक्षम बनाता है।

एरे डीस्ट्रक्चरिंग

// वैरिएबल असाइनमेंट। const foo = ['one', 'two', 'three']; const [one, two, three] = foo; console.log(one); // "one" console.log(two); // "two" console.log(three); // "three"
// वैरिएबल स्वैपिंग let a = 1; let b = 3; [a, b] = [b, a]; console.log(a); // 3 console.log(b); // 1

ऑब्जेक्ट डीस्ट्रक्चरिंग

// वैरिएबल असाइनमेंट। const o = { p: 42, q: true }; const { p, q } = o; console.log(p); // 42 console.log(q); // true

ES6 टेम्प्लेट लिटरल स्ट्रिंग बनाने में बहुत लचीलापन प्रदान करते हैं, क्या आप एक उदाहरण दे सकते हैं?

टेम्प्लेट लिटरल स्ट्रिंग इंटरपोलेशन को सरल बनाने में मदद करते हैं, या स्ट्रिंग में वैरिएबल शामिल करने में मदद करते हैं। ES2015 से पहले, ऐसा कुछ करना आम था:

var person = { name: 'Tyler', age: 28 }; console.log( 'Hi, my name is ' + person.name + ' and I am ' + person.age + ' years old!', ); // 'Hi, my name is Tyler and I am 28 years old!'

टेम्प्लेट लिटरल के साथ, आप अब उसी आउटपुट को ऐसे बना सकते हैं:

const person = { name: 'Tyler', age: 28 }; console.log(`Hi, my name is ${person.name} and I am ${person.age} years old!`); // 'Hi, my name is Tyler and I am 28 years old!'

ध्यान दें कि आप बैकटिक्स का उपयोग करते हैं, न कि कोट्स का, यह इंगित करने के लिए कि आप एक टेम्प्लेट लिटरल का उपयोग कर रहे हैं और आप ${} प्लेसहोल्डर्स के अंदर एक्सप्रेशन डाल सकते हैं।

एक दूसरा सहायक उपयोग मामला मल्टी-लाइन स्ट्रिंग्स बनाने में है। ES2015 से पहले, आप इस तरह एक मल्टी-लाइन स्ट्रिंग बना सकते थे:

console.log('This is line one.\nThis is line two.'); // यह पहली पंक्ति है। // यह दूसरी पंक्ति है।

या यदि आप इसे अपने कोड में कई लाइनों में तोड़ना चाहते थे ताकि आपको एक लंबी स्ट्रिंग पढ़ने के लिए अपने टेक्स्ट एडिटर में दाईं ओर स्क्रॉल न करना पड़े, तो आप इसे इस तरह भी लिख सकते थे:

console.log('This is line one.\n' + 'This is line two.'); // यह पहली पंक्ति है। // यह दूसरी पंक्ति है।

हालांकि, टेम्प्लेट लिटरल आपके द्वारा उनमें जोड़े गए किसी भी स्पेसिंग को संरक्षित करते हैं। उदाहरण के लिए, हमने ऊपर जो समान मल्टी-लाइन आउटपुट बनाया है, उसे बनाने के लिए, आप बस ऐसा कर सकते हैं:

console.log(`This is line one. This is line two.`); // यह पहली पंक्ति है। // यह दूसरी पंक्ति है।

टेम्प्लेट लिटरल का एक और उपयोग मामला सरल वैरिएबल इंटरपोलेशन के लिए टेम्प्लेटिंग लाइब्रेरी के विकल्प के रूप में उपयोग करना होगा:

const person = { name: 'Tyler', age: 28 }; document.body.innerHTML = ` <div> <p>नाम: ${person.name}</p> <p>आयु: ${person.age}</p> </div> `;

ध्यान दें कि आपका कोड .innerHTML का उपयोग करके XSS के प्रति संवेदनशील हो सकता है। यदि डेटा उपयोगकर्ता से आया है तो उसे प्रदर्शित करने से पहले सैनिटाइज करें!

क्या आप करी फ़ंक्शन का एक उदाहरण दे सकते हैं और यह सिंटैक्स एक लाभ क्यों प्रदान करता है?

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

function curry(fn) { if (fn.length === 0) { return fn; } function _curried(depth, args) { return function (newArgument) { if (depth - 1 === 0) { return fn(...args, newArgument); } return _curried(depth - 1, [...args, newArgument]); }; } return _curried(fn.length, []); } function add(a, b) { return a + b; } var curriedAdd = curry(add); var addFive = curriedAdd(5); var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]

स्प्रेड सिंटैक्स का उपयोग करने के क्या लाभ हैं और यह रेस्ट सिंटैक्स से कैसे अलग है?

ES6 का स्प्रेड सिंटैक्स कार्यात्मक प्रतिमान में कोडिंग करते समय बहुत उपयोगी होता है क्योंकि हम Object.create, slice, या किसी लाइब्रेरी फ़ंक्शन का सहारा लिए बिना सरलता से सरणियों या वस्तुओं की प्रतियां बना सकते हैं। यह भाषा सुविधा Redux और RxJS परियोजनाओं में अक्सर उपयोग की जाती है।

function putDookieInAnyArray(arr) { return [...arr, 'dookie']; } const result = putDookieInAnyArray(['I', 'really', "don't", 'like']); // ["I", "really", "don't", "like", "dookie"] const person = { name: 'Todd', age: 29, }; const copyOfTodd = { ...person };

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

function addFiveToABunchOfNumbers(...numbers) { return numbers.map((x) => x + 5); } const result = addFiveToABunchOfNumbers(4, 5, 6, 7, 8, 9, 10); // [9, 10, 11, 12, 13, 14, 15] const [a, b, ...rest] = [1, 2, 3, 4]; // a: 1, b: 2, rest: [3, 4] const { e, f, ...others } = { e: 1, f: 2, g: 3, h: 4, }; // e: 1, f: 2, others: { g: 3, h: 4 }

आप फ़ाइलों के बीच कोड कैसे साझा कर सकते हैं?

यह जावास्क्रिप्ट वातावरण पर निर्भर करता है।

क्लाइंट (ब्राउज़र वातावरण) पर, जब तक वैरिएबल/फ़ंक्शन वैश्विक दायरे (window) में घोषित किए जाते हैं, तब तक सभी स्क्रिप्ट उन्हें संदर्भित कर सकती हैं। वैकल्पिक रूप से, अधिक मॉड्यूलर दृष्टिकोण के लिए RequireJS के माध्यम से एसिंक्रोनस मॉड्यूल डेफिनिशन (AMD) अपनाएं।

सर्वर (Node.js) पर, सामान्य तरीका CommonJS का उपयोग करना रहा है। प्रत्येक फ़ाइल को एक मॉड्यूल के रूप में माना जाता है और यह module.exports ऑब्जेक्ट से जोड़कर वैरिएबल और फ़ंक्शन को एक्सपोर्ट कर सकता है।

ES2015 एक मॉड्यूल सिंटैक्स को परिभाषित करता है जिसका उद्देश्य AMD और CommonJS दोनों को बदलना है। यह अंततः ब्राउज़र और नोड दोनों वातावरणों में समर्थित होगा।

आप स्थिर क्लास सदस्यों को क्यों बनाना चाहेंगे?

स्थिर क्लास सदस्य (गुण/विधियाँ) एक क्लास के किसी विशिष्ट इंस्टेंस से बंधे नहीं होते हैं और जिस भी इंस्टेंस द्वारा इसे संदर्भित किया जाता है, उसका मान समान होता है। स्थिर गुण आमतौर पर कॉन्फ़िगरेशन वैरिएबल होते हैं और स्थिर विधियाँ आमतौर पर शुद्ध उपयोगिता फ़ंक्शन होती हैं जो इंस्टेंस की स्थिति पर निर्भर नहीं करती हैं।