Eksternal dan Ekspor
Tetap teratur dengan koleksi
Simpan dan kategorikan konten berdasarkan preferensi Anda.
Tujuan Magang
Extern adalah deklarasi yang memberi tahu Closure Compiler nama simbol yang tidak boleh diganti namanya selama kompilasi lanjutan.
Simbol ini disebut extern karena paling sering ditentukan oleh
kode di luar kompilasi, seperti kode native, atau library
pihak ketiga. Oleh karena itu, externs sering kali juga memiliki anotasi jenis,
sehingga Closure Compiler dapat memeriksa jenis penggunaan simbol tersebut.
Secara umum, sebaiknya anggap extern sebagai kontrak API antara
pelaksana dan konsumen beberapa bagian kode yang dikompilasi. Eksternal
menentukan apa yang dijanjikan oleh pelaksana untuk disediakan, dan apa yang
dapat diandalkan oleh konsumen. Kedua belah pihak memerlukan salinan kontrak.
Extern mirip dengan file header dalam bahasa lain.
Sintaksis Eksternal
Extern adalah file yang sangat mirip dengan JavaScript normal yang diberi anotasi
untuk Closure Compiler. Perbedaan utamanya adalah bahwa kontennya tidak pernah dicetak
sebagai bagian dari output yang dikompilasi, sehingga tidak ada nilai yang bermakna,
hanya nama dan jenisnya.
Berikut adalah contoh file externs untuk library sederhana.
// 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) {};
Bendera --externs
Secara umum, anotasi @externs
adalah cara terbaik untuk memberi tahu
compiler bahwa file berisi eksternal. File tersebut dapat disertakan
sebagai file sumber normal menggunakan tanda command line --js
,
Namun, ada cara lain yang lebih lama untuk menentukan file eksternal. Flag
command line --externs
dapat digunakan untuk meneruskan file
extern secara eksplisit. Metode ini tidak disarankan.
Menggunakan Eksternal
Eksternal dari atas dapat digunakan sebagai berikut.
/**
* @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;
}
Tujuan Ekspor
Ekspor adalah mekanisme lain untuk memberikan nama yang konsisten pada simbol setelah
kompilasi. Ekspor ini kurang berguna dibandingkan eksternal dan sering kali membingungkan. Untuk
semua kasus kecuali yang sederhana, sebaiknya hindari penggunaan metode ini.
Ekspor bergantung pada fakta bahwa Closure Compiler tidak mengubah literal string.
Dengan menetapkan objek ke properti yang dinamai menggunakan literal, objek akan tersedia melalui nama properti tersebut meskipun setelah kompilasi.
Berikut adalah contoh sederhana.
/**
* @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;
Jika Anda menggunakan Closure Library, ekspor juga dapat dideklarasikan menggunakan
fungsi goog.exportSymbol
dan goog.exportProperty
.
Informasi selengkapnya tersedia dalam dokumentasi Closure Library tentang
fungsi ini. Namun, perlu diketahui bahwa mereka memiliki dukungan compiler khusus
dan akan diubah sepenuhnya dalam output yang dikompilasi.
Masalah terkait Ekspor
Ekspor berbeda dari eksternal karena hanya membuat
alias yang terekspos untuk dirujuk konsumen. Dalam kode yang dikompilasi, simbol yang diekspor
akan tetap diganti namanya. Oleh karena itu, simbol yang diekspor harus berupa
konstanta, karena menetapkannya kembali dalam kode akan menyebabkan alias
yang diekspos menunjuk ke hal yang salah.
Perubahan nama yang halus ini sangat rumit, terutama terkait dengan properti instance yang diekspor.
Secara teori, ekspor dapat menghasilkan ukuran kode yang lebih kecil dibandingkan dengan eksternal, karena nama yang panjang masih dapat diubah menjadi nama yang lebih pendek dalam kode Anda. Dalam praktiknya,
peningkatan ini sering kali sangat kecil, dan tidak membenarkan kebingungan yang disebabkan oleh ekspor.
Ekspor juga tidak menyediakan API yang dapat diikuti konsumen seperti yang dilakukan extern.
Dibandingkan dengan ekspor, extern mendokumentasikan simbol yang ingin Anda ekspos,
jenisnya, dan memberi Anda tempat untuk menambahkan informasi penggunaan. Selain itu,
jika konsumen Anda juga menggunakan Closure Compiler, mereka akan memerlukan file ekstern untuk
dikompilasi.
Kecuali dinyatakan lain, konten di halaman ini dilisensikan berdasarkan Lisensi Creative Commons Attribution 4.0, sedangkan contoh kode dilisensikan berdasarkan Lisensi Apache 2.0. Untuk mengetahui informasi selengkapnya, lihat Kebijakan Situs Google Developers. Java adalah merek dagang terdaftar dari Oracle dan/atau afiliasinya.
Terakhir diperbarui pada 2025-07-26 UTC.
[[["Mudah dipahami","easyToUnderstand","thumb-up"],["Memecahkan masalah saya","solvedMyProblem","thumb-up"],["Lainnya","otherUp","thumb-up"]],[["Informasi yang saya butuhkan tidak ada","missingTheInformationINeed","thumb-down"],["Terlalu rumit/langkahnya terlalu banyak","tooComplicatedTooManySteps","thumb-down"],["Sudah usang","outOfDate","thumb-down"],["Masalah terjemahan","translationIssue","thumb-down"],["Masalah kode / contoh","samplesCodeIssue","thumb-down"],["Lainnya","otherDown","thumb-down"]],["Terakhir diperbarui pada 2025-07-26 UTC."],[[["\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."]]