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.