एक्सटर्न का मकसद
Externs ऐसे एलान होते हैं जिनसे Closure Compiler को उन सिंबल के नाम पता चलते हैं जिन्हें ऐडवांस कंपाइलेशन के दौरान बदला नहीं जाना चाहिए. इन्हें एक्सटर्न कहा जाता है, क्योंकि इन सिंबल को अक्सर कंपाइलेशन के बाहर के कोड से तय किया जाता है. जैसे, नेटिव कोड या तीसरे पक्ष की लाइब्रेरी. इस वजह से, बाहरी सिंबल में अक्सर टाइप एनोटेशन भी होते हैं, ताकि Closure Compiler उन सिंबल के इस्तेमाल की टाइप जांच कर सके.
आम तौर पर, एक्सटर्न को एपीआई अनुबंध के तौर पर देखा जाता है. यह अनुबंध, लागू करने वाले और कंपाइल किए गए कोड के उपभोक्ताओं के बीच होता है. एक्सटर्न से यह तय होता है कि लागू करने वाला व्यक्ति क्या-क्या उपलब्ध कराएगा. साथ ही, उपभोक्ता किन चीज़ों का इस्तेमाल कर सकते हैं. दोनों पक्षों के पास कानूनी समझौते की एक कॉपी होनी चाहिए.
एक्सटर्न, अन्य भाषाओं में हेडर फ़ाइलों की तरह होते हैं.
Externs सिंटैक्स
Externs ऐसी फ़ाइलें होती हैं जो Closure Compiler के लिए एनोटेट की गई सामान्य JavaScript फ़ाइलों की तरह दिखती हैं. इनके बीच मुख्य अंतर यह है कि इनके कॉन्टेंट को कभी भी कंपाइल किए गए आउटपुट के हिस्से के तौर पर प्रिंट नहीं किया जाता. इसलिए, इनमें से कोई भी वैल्यू काम की नहीं होती. सिर्फ़ नाम और टाइप काम के होते हैं.
यहां एक सामान्य लाइब्रेरी के लिए, बाहरी फ़ाइल का उदाहरण दिया गया है.
// The `@externs` annotation is the best way to indicate a file contains externs. /** * @fileoverview Public API of my_math.js. * @externs */ // Externs often declare global namespaces. const myMath = {}; // Externs can declare functions, most importantly their names. /** * @param {number} x * @param {number} y * @return {!myMath.DivResult} */ myMath.div = function(x, y) {}; // Note the empty body. // Externs can contain type declarations, such as classes and interfaces. /** The result of an integer division. */ myMath.DivResult = class { // Constructors are special; member fields can be declared in their bodies. constructor() { /** @type {number} */ this.quotient; /** @type {number} */ this.remainder; } // Methods can be declared as usual; their bodies are meaningless though. /** @return {!Array<number>} */ toPair() {} }; // Fields and methods can also be declared using prototype notation. /** * @override * @param {number=} radix */ myMath.DivResult.prototype.toString = function(radix) {};
--externs
का झंडा
आम तौर पर, @externs
एनोटेशन, कंपाइलर को यह बताने का सबसे अच्छा तरीका है कि किसी फ़ाइल में बाहरी फ़ंक्शन शामिल हैं. --js
कमांड-लाइन फ़्लैग का इस्तेमाल करके, ऐसी फ़ाइलों को सामान्य सोर्स फ़ाइलों के तौर पर शामिल किया जा सकता है,
हालांकि, externs फ़ाइलों को तय करने का एक और पुराना तरीका है. --externs
कमांड-लाइन फ़्लैग का इस्तेमाल करके, एक्सटर्न फ़ाइलों को साफ़ तौर पर पास किया जा सकता है. हम इस तरीके का सुझाव नहीं देते.
Externs का इस्तेमाल करना
ऊपर दिए गए एक्सटर्न का इस्तेमाल इस तरह किया जा सकता है.
/** * @fileoverview Do some math. */ /** * @param {number} x * @param {number} y * @return {number} */ export function greatestCommonDivisor(x, y) { while (y != 0) { const temp = y; // `myMath` is a global, it and `myMath.div` are never renamed. const result = myMath.div(x, y); // `remainder` is also never renamed on instances of `DivResult`. y = result.remainder; x = temp; } return x; }
एक्सपोर्ट करने का मकसद
एक्सपोर्ट, कंपाइल करने के बाद सिंबल को एक जैसे नाम देने का एक और तरीका है. ये इंटर्न की तुलना में कम फ़ायदेमंद होते हैं और अक्सर भ्रमित करने वाले होते हैं. हालांकि, सामान्य मामलों को छोड़कर, अन्य सभी मामलों में इनका इस्तेमाल नहीं करना चाहिए.
एक्सपोर्ट इस बात पर निर्भर करते हैं कि Closure Compiler, स्ट्रिंग लिटरल में बदलाव नहीं करता है. किसी ऑब्जेक्ट को लिटरल का इस्तेमाल करके नाम वाली प्रॉपर्टी असाइन करने पर, कंपाइल करने के बाद भी ऑब्जेक्ट उस प्रॉपर्टी के नाम से उपलब्ध रहेगा.
यहां एक सामान्य उदाहरण दिया गया है.
/** * @fileoverview Do some math. */ // Note that the concept of module exports is totally unrelated. /** @return {number} */ export function myFunction() { return 5; } // This assignment ensures `myFunctionAlias` will be a global alias exposing `myFunction`, // even after compilation. window['myFunctionAlias'] = myFunction;
Closure Library का इस्तेमाल करने पर, एक्सपोर्ट को goog.exportSymbol
और goog.exportProperty
फ़ंक्शन का इस्तेमाल करके भी एलान किया जा सकता है.
इन फ़ंक्शन के बारे में ज़्यादा जानकारी, Closure Library के दस्तावेज़ में उपलब्ध है. हालांकि, ध्यान रखें कि इनके लिए खास कंपाइलर सपोर्ट उपलब्ध है. साथ ही, कंपाइल किए गए आउटपुट में इन्हें पूरी तरह से बदल दिया जाएगा.
एक्सपोर्ट से जुड़ी समस्याएं
एक्सपोर्ट, एक्सटर्न से इस मामले में अलग होते हैं कि वे सिर्फ़ उपभोक्ताओं के लिए, ऐक्सेस किया गया एलियास बनाते हैं, ताकि वे इसका रेफ़रंस दे सकें. कंपाइल किए गए कोड में, एक्सपोर्ट किए गए सिंबल का नाम अब भी बदला जाएगा. इस वजह से, एक्सपोर्ट किए गए सिंबल हमेशा एक जैसे होने चाहिए. ऐसा इसलिए, क्योंकि कोड में उन्हें फिर से असाइन करने पर, ऐक्सेस किए गए एलियास गलत चीज़ की ओर इशारा करेंगे.
नाम बदलने की इस बारीकी को समझना, एक्सपोर्ट की गई इंस्टेंस प्रॉपर्टी के मामले में खास तौर पर मुश्किल होता है.
सैद्धांतिक तौर पर, एक्सपोर्ट से कोड का साइज़, बाहरी फ़ाइलों की तुलना में छोटा हो सकता है. ऐसा इसलिए, क्योंकि लंबे नामों को अब भी आपके कोड में छोटे नामों में बदला जा सकता है. असल में, इन सुधारों से बहुत कम फ़र्क़ पड़ता है. साथ ही, एक्सपोर्ट से होने वाली गड़बड़ियों को सही नहीं किया जा सकता.
एक्सपोर्ट में, उपभोक्ताओं के लिए ऐसा एपीआई भी उपलब्ध नहीं होता है जिसका इस्तेमाल करके वे एक्सटर्न की तरह काम कर सकें. एक्सपोर्ट की तुलना में, एक्सटर्न उन सिंबल के बारे में जानकारी देते हैं जिन्हें आपको दिखाना है. साथ ही, वे उनके टाइप के बारे में बताते हैं और आपको इस्तेमाल से जुड़ी जानकारी जोड़ने की जगह देते हैं. इसके अलावा, अगर आपके उपभोक्ता भी Closure Compiler का इस्तेमाल कर रहे हैं, तो उन्हें कंपाइल करने के लिए externs की ज़रूरत होगी.