خارجی و صادرات
با مجموعهها، منظم بمانید
ذخیره و طبقهبندی محتوا براساس اولویتهای شما.
هدف خارجی ها
خارجی ها اعلان هایی هستند که به Closure Compiler نام نمادهایی را می گویند که نباید در طول کامپایل پیشرفته تغییر نام دهند. آنها خارجی نامیده می شوند زیرا این نمادها اغلب با کد خارج از کامپایل، مانند کد بومی یا کتابخانه های شخص ثالث تعریف می شوند. به همین دلیل، خارجی ها اغلب دارای حاشیه نویسی نوع نیز هستند، به طوری که Closure Compiler می تواند استفاده شما از آن نمادها را تایپ کند.
به طور کلی، بهتر است خارجیها را به عنوان یک قرارداد API بین پیادهکننده و مصرفکنندگان برخی از کدهای کامپایلشده در نظر بگیریم. خارجی ها تعریف می کنند که مجری چه چیزی را عرضه می کند و مصرف کنندگان می توانند از چه چیزهایی استفاده کنند. هر دو طرف به یک کپی از قرارداد نیاز دارند.
اکسترن ها مشابه فایل های هدر در زبان های دیگر هستند.
نحو خارجی
اکسترن ها فایل هایی هستند که بسیار شبیه جاوا اسکریپت معمولی حاشیه نویسی شده برای Closure Compiler هستند. تفاوت اصلی این است که محتویات آنها هرگز به عنوان بخشی از خروجی کامپایل شده چاپ نمی شود، بنابراین هیچ یک از مقادیر معنی دار نیستند، فقط نام ها و انواع آنها معنادار است.
در زیر نمونه ای از فایل externs برای یک کتابخانه ساده آورده شده است.
// 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 استفاده کرد. این روش توصیه نمی شود.
استفاده از 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;
}
هدف از صادرات
صادرات مکانیسم دیگری برای نامگذاری یکنواخت نمادها پس از تدوین است. آنها کمتر از خارجی ها مفید هستند و اغلب گیج کننده هستند. برای همه موارد به جز موارد ساده بهتر است از آنها اجتناب شود.
صادرات متکی به این واقعیت است که کامپایلر بسته شدن، حروف الفبای رشته را تغییر نمی دهد. با انتساب یک شی به یک ویژگی که با استفاده از literal نامگذاری شده است، شی از طریق آن نام ویژگی حتی پس از کامپایل در دسترس خواهد بود.
در زیر یک مثال ساده آورده شده است.
/**
* @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;
اگر از کتابخانه بسته استفاده می کنید، صادرات را می توان با استفاده از توابع goog.exportSymbol
و goog.exportProperty
نیز اعلام کرد.
اطلاعات بیشتر در مستندات کتابخانه بسته شدن این عملکردها موجود است. با این حال، توجه داشته باشید که آنها پشتیبانی کامپایلر ویژه ای دارند و به طور کامل در خروجی کامپایل شده تغییر خواهند کرد.
مسائل مربوط به صادرات
صادرات با خارجی متفاوت است زیرا آنها فقط یک نام مستعار در معرض دید مصرف کنندگان ایجاد می کنند تا به آنها مراجعه کنند. در کد کامپایل شده، نماد صادر شده همچنان تغییر نام خواهد داشت. به همین دلیل، نمادهای صادر شده باید ثابت باشند، زیرا تخصیص مجدد آنها در کد شما باعث میشود که نام مستعار آشکار شده به چیزی اشتباه اشاره کند.
این ظرافت در تغییر نام به ویژه با توجه به ویژگی های نمونه صادراتی پیچیده است.
در تئوری، صادرات میتواند اندازه کد کوچکتری را در مقایسه با خارجیها مجاز کند، زیرا نامهای طولانی را میتوان به نامهای کوتاهتر در کد شما تغییر داد. در عمل، این پیشرفتها اغلب بسیار جزئی هستند و سردرگمی ایجاد شده توسط صادرات را توجیه نمیکنند.
صادرات همچنین یک API برای مصرفکنندگان ارائه نمیکند تا آنطور که خارجیها از آن پیروی میکنند. در مقایسه با صادرات، خارجی ها نمادهایی را که می خواهید در معرض نمایش بگذارید، انواع آنها را مستند می کنند و مکانی برای اضافه کردن اطلاعات استفاده در اختیار شما قرار می دهند. علاوه بر این، اگر مصرف کنندگان شما از Closure Compiler نیز استفاده می کنند، برای کامپایل نیاز به خارجی دارند.
جز در مواردی که غیر از این ذکر شده باشد،محتوای این صفحه تحت مجوز Creative Commons Attribution 4.0 License است. نمونه کدها نیز دارای مجوز Apache 2.0 License است. برای اطلاع از جزئیات، به خطمشیهای سایت Google Developers مراجعه کنید. جاوا علامت تجاری ثبتشده Oracle و/یا شرکتهای وابسته به آن است.
تاریخ آخرین بهروزرسانی 2025-07-24 بهوقت ساعت هماهنگ جهانی.
[null,null,["تاریخ آخرین بهروزرسانی 2025-07-24 بهوقت ساعت هماهنگ جهانی."],[[["\u003cp\u003eExterns are declarations that inform Closure Compiler about external symbols (like those from native code or third-party libraries) that should not be renamed during compilation.\u003c/p\u003e\n"],["\u003cp\u003eThey act as an API contract, defining what symbols are provided and ensuring type safety by including type annotations.\u003c/p\u003e\n"],["\u003cp\u003eExterns are primarily defined in separate files using the \u003ccode\u003e@externs\u003c/code\u003e annotation, similar to header files in other languages.\u003c/p\u003e\n"],["\u003cp\u003eWhile exports offer an alternative for exposing symbols, they are less versatile than externs and can introduce complexities, making externs generally preferred.\u003c/p\u003e\n"],["\u003cp\u003eExports create aliases for symbols, while externs provide comprehensive API documentation and type information for external code interaction.\u003c/p\u003e\n"]]],[],null,["# Externs and Exports\n\nPurpose of Externs\n------------------\n\n\nExterns are declarations that tell Closure Compiler the names of\nsymbols that should not be renamed during advanced compilation.\nThey are called externs because these symbols are most often defined by\ncode outside the compilation, such a native code, or third-party\nlibraries. For this reason, externs often also have type annotations,\nso that Closure Compiler can typecheck your use of those symbols.\n\n\nIn general, it is best to think of externs as an API contract between\nthe implementor and the consumers of some piece of compiled code. The\nexterns define what the implementor promises to supply, and what the\nconsumers can depend on using. Both sides need a copy of the contract.\n\nExterns are similar to header files in other languages. \n\nExterns Syntax\n--------------\n\n\nExterns are files that look very much like normal JavaScript annotated\nfor Closure Compiler. The main difference is that their contents are never printed\nas part of the compiled output, so none of the values are meaningful,\nonly the names and types.\n\nBelow is an example of an externs file for a simple library. \n\n```gdscript\n// The `@externs` annotation is the best way to indicate a file contains externs.\n\n/**\n * @fileoverview Public API of my_math.js.\n * @externs\n */\n\n// Externs often declare global namespaces.\n\nconst myMath = {};\n\n// Externs can declare functions, most importantly their names.\n\n/**\n * @param {number} x\n * @param {number} y\n * @return {!myMath.DivResult}\n */\nmyMath.div = function(x, y) {}; // Note the empty body.\n\n// Externs can contain type declarations, such as classes and interfaces.\n\n/** The result of an integer division. */\nmyMath.DivResult = class {\n\n // Constructors are special; member fields can be declared in their bodies.\n\n constructor() {\n /** @type {number} */\n this.quotient;\n /** @type {number} */\n this.remainder;\n }\n\n // Methods can be declared as usual; their bodies are meaningless though.\n\n /** @return {!Array\u003cnumber\u003e} */\n toPair() {}\n\n};\n\n// Fields and methods can also be declared using prototype notation.\n\n/**\n * @override\n * @param {number=} radix\n */\nmyMath.DivResult.prototype.toString = function(radix) {};\n \n``` \n\n### The `--externs` Flag\n\n\nGenerally, the `@externs` annotation is the best way to inform\nthe compiler that a file contains externs. Such files can be included\nas normal source files using the `--js` command-line flag,\n\n\nHowever, there is another, older way, to specify externs files. The\n`--externs` command-line flag can be used to pass externs\nfiles explicitly. This method is not recommended. \n\nUsing Externs\n-------------\n\nThe externs from above can be consumed as follows. \n\n```mysql\n/**\n * @fileoverview Do some math.\n */\n\n/**\n * @param {number} x\n * @param {number} y\n * @return {number}\n */\nexport function greatestCommonDivisor(x, y) {\n while (y != 0) {\n const temp = y;\n // `myMath` is a global, it and `myMath.div` are never renamed.\n const result = myMath.div(x, y);\n // `remainder` is also never renamed on instances of `DivResult`.\n y = result.remainder;\n x = temp;\n }\n return x;\n}\n \n``` \n\nPurpose of Exports\n------------------\n\n\nExports are another mechanism for giving symbols consistent names after\ncompilation. They are less useful than externs and often confusing. For\nall but simple cases they are best avoided.\n\n\nExports rely on the fact that Closure Compiler doesn't modify string literals.\nBy assigning an object to a property named using a literal, the object will\nbe available through that property name even after compilation.\n\n\nBelow is a simple example. \n\n```mysql\n/**\n * @fileoverview Do some math.\n */\n\n// Note that the concept of module exports is totally unrelated.\n\n/** @return {number} */\nexport function myFunction() {\n return 5;\n}\n\n// This assignment ensures `myFunctionAlias` will be a global alias exposing `myFunction`,\n// even after compilation.\n\nwindow['myFunctionAlias'] = myFunction;\n \n``` \n\nIf you are using Closure Library, exports can also be declared using the\n`goog.exportSymbol` and `goog.exportProperty` functions.\n\n\nMore information is available in the Closure Library documentation of\nthese functions. However, be aware they have special compiler support\nand will be totally transformed in the compiled output. \n\nIssues with Exports\n-------------------\n\n\nExports are different from externs in that they only create an exposed\n*alias* for consumers to reference. Within the compiled code, the exported\nsymbol will still be renamed. For this reason, exported symbols must be\nconstant, since reassigning them in your code would cause the exposed\nalias to point to the wrong thing.\n\n\nThis subtlety in renaming is especially complicated with respect to exported\ninstance properties.\n\n\nIn theory, exports can allow smaller code-size compared to externs, since long\nnames can still be changed to shorter ones within your code. In practice,\nthese improvements are often very minor, and don't justify the confusion exports create.\n\n\nExports also don't provide an API for consumers to follow in the way externs do.\nCompared to exports, externs document the symbols you intend to expose,\ntheir types, and give you a place to add usage information. Additionally,\nif your consumers are also using Closure Compiler, they will need externs to\ncompile against."]]