Mari kita mulai artikel ini dengan sebuah pertanyaan. Modul ES2015 increment
berisi kode berikut:
let counter = 0;
counter++;
export default counter;
Dalam modul lain, yang akan kita panggil consumer
, modul di atas diimpor 2 kali:
import counter1 from './increment';
import counter2 from './increment';
counter1;
counter2;
Dan sekarang, sebenarnya, sebuah pertanyaan. Apa yang masuk dalam variabel counter1
dan counter2
setelah modul consumer
? Untuk menjawab pertanyaan ini, Anda perlu memahami bagaimana JavaScript mengeksekusi modul, dan bagaimana mereka diimpor.
Eksekusi modul
Untuk memahami bagaimana mekanisme JavaScript internal berfungsi, penting untuk melihat spesifikasi .Menurut spesifikasi, setiap modul JavaScript dikaitkan dengan entitas Record Modul . Entri ini memiliki metode Evaluate()
yang dijalankan oleh modul:Jika modul ini telah berhasil dieksekusi, kembalikan tidak terdefinisi; [...] Jika tidak, jalankan semua dependensi dari modul ini secara transparan dan kemudian jalankan modul ini.Hasilnya, ternyata modul yang sama dijalankan hanya sekali.Sayangnya, apa yang perlu Anda ketahui untuk menjawab pertanyaan kami tidak terbatas pada ini. Cara memastikan bahwa panggilan instruksiimport
menggunakan jalur yang sama akan mengembalikan modul yang sama?Izinkan perintah impor
Operasi abstrak HostResolveImportedModule () bertanggung jawab untuk mengaitkan path ke modul (specifier) ββdengan modul tertentu . Kode impor modul terlihat seperti ini:import module from 'path';
Berikut adalah apa yang dikatakan oleh spec tentang itu:Implementasi HostResolveImportedModule harus memenuhi persyaratan berikut:- Nilai pengembalian normal harus merupakan turunan dari subkelas tertentu dari Catatan Modul.
- Jika entitas Record Modul yang sesuai dengan pasangan referensi ScriptOrModule, specifier tidak ada, atau entitas seperti itu tidak dapat dibuat, pengecualian harus dilemparkan.
- Setiap kali operasi ini dipanggil dengan memberikannya sebagai argumen sepasang referensiencingScriptOrModule, specifier, ia harus, dalam kasus eksekusi yang biasa, mengembalikan instance yang sama dari entitas Record Modul.
Sekarang pertimbangkan ini dengan cara yang lebih dimengerti.HostResolveImportedModule(referencingScriptOrModule, specifier)
- sebuah operasi abstrak yang kembali modul sesuai dengan sepasang parameter referencingScriptOrModule
, specifier
:- Parameternya
referencingScriptOrModule
adalah modul saat ini, yaitu modul yang mengimpor. - Parameter
specifier
adalah string yang cocok dengan lintasan modul dalam instruksi import
.
Pada akhir deskripsi, HostResolveImportedModule()
dikatakan bahwa ketika mengimpor modul yang sesuai dengan jalur yang sama, modul yang sama diimpor:import moduleA from 'path';
import moduleB from 'path';
import moduleC from 'path';
moduleA === moduleB;
moduleB === moduleC;
Menariknya, spesifikasi menunjukkan bahwa host (browser, lingkungan Node.js, secara umum - apa pun yang mencoba mengeksekusi kode JavaScript) harus menyediakan implementasi spesifik HostResolveImportedModule()
.Menjawab
Setelah membaca spesifikasi dengan cermat, menjadi jelas bahwa modul JavaScript dieksekusi hanya sekali selama impor. Dan ketika mengimpor modul menggunakan jalur yang sama, instance modul yang sama dikembalikan.Mari kita kembali ke pertanyaan kita.Modul increment
selalu dijalankan hanya sekali:
let counter = 0;
counter++;
export default counter;
Terlepas dari berapa kali modul diimpor increment
, ekspresi counter++
hanya dievaluasi satu kali. Variabel yang counter
diekspor menggunakan mekanisme ekspor standar penting 1
.Sekarang lihat modul consumer
:
import counter1 from './increment';
import counter2 from './increment';
counter1;
counter2;
Perintah import counter1 from './increment'
dan import counter2 from './increment'
gunakan jalur yang sama - './increment'
. Hasilnya, ternyata instance modul yang sama diimpor.Ternyata nilai yang sama 1 ditulis ke variabel counter1
dan counter2
ke consumer
.Ringkasan
Setelah memeriksa pertanyaan sederhana, kami dapat mengetahui lebih lanjut tentang bagaimana modul JavaScript dieksekusi dan diimpor.Aturan yang digunakan saat mengimpor modul cukup sederhana: modul yang sama dijalankan hanya sekali. Dengan kata lain, apa yang ada dalam lingkup level modul hanya dilakukan sekali. Jika modul yang sudah dijalankan sekali diimpor kembali, maka tidak akan dieksekusi lagi. Saat mengimpor modul, modul ini menggunakan apa yang diperoleh sebagai hasil dari sesi sebelumnya untuk mengetahui apa yang sebenarnya diekspor.Jika suatu modul diimpor beberapa kali, tetapi penentu modul (jalur ke sana) tetap sama, spesifikasi JavaScript memastikan bahwa instance modul yang sama diimpor.Pembaca yang budiman! Seberapa sering Anda resor untuk membaca spesifikasi JavaScript, mencari tahu fitur fungsi konstruksi bahasa tertentu?