Enjin JS:
- Program yang melaksanakan kod JS. Cth. V8 Google.
- V8 kuasa Chrome, Node.js
- Pelayar lain mempunyai Enjin JS mereka sendiri.
Enjin JS mempunyai 2 bahagian:
- Timbunan Panggilan: Tempat kod kami dilaksanakan menggunakan konteks pelaksanaan.
- Timbunan: Kumpulan memori tidak berstruktur, digunakan untuk menyimpan objek.
Setiap program c/r perlu ditukar kepada kod mesin. Dilakukan melalui dua proses:
1. Penyusunan: Keseluruhan kod ditukar kepada kod mesin sekaligus, ditulis kepada fail binari yang boleh dilaksanakan oleh komputer.
Kod Sumber -(disusun)-> Kod Binari[Fail Mudah Alih] -(dilaksanakan)-> Pgm Run
Pelaksanaan boleh berlaku selepas kompilasi.
2. Tafsiran: Jurubahasa berjalan melalui kod sumber, melaksanakannya baris demi baris.
Kod sumber -(pelaksanaan baris demi baris)-> Pgm Run
- Kod di sini masih perlu ditukar kepada kod mesin.
- Ia jauh lebih perlahan berbanding dengan l/gs yang disusun.
3. JIT iaitu Kompilasi Tepat Masa:
- Enjin JS Moden ialah gabungan kompilasi & tafsiran untuk menjadikannya pantas.
- Keseluruhan kod ditukar kepada kod mesin sekaligus, kemudian dilaksanakan serta-merta.
Kod Sumber -(disusun)-> Kod mesin -(dilaksanakan)-> Pgm Run
- Tiada fail mudah alih perantaraan untuk dilaksanakan.
- Pelaksanaan berlaku serta-merta selepas penyusunan.
- Oleh itu, JS kini jauh lebih pantas daripada l/gs yang ditafsirkan kerana teknik ini.
Proses Penyusunan dalam JS:
Langkah 1. Menghuraikan:
- Kod kami dihuraikan iaitu dibaca oleh enjin JS ke dalam AST atau Pokok Sintaks Abstrak.
- Berfungsi dengan membahagikan kod kepada pokok berdasarkan kata kunci seperti const, let, function dll yang bermakna kepada l/g.
- Kemudian simpan kod ke dalam pokok secara berstruktur.
- Semak juga untuk sebarang ralat sintaks.
- AST tiada kaitan dengan pokok DOM. AST hanyalah perwakilan kod kami di dalam Enjin JS.
Langkah 2, 3[digabungkan]: Penyusunan + Pelaksanaan
- AST disusun dan segera dilaksanakan selepasnya, menggunakan JIT.
- Pelaksanaan berlaku dalam tindanan Panggilan.
- JS moden mempunyai strategi pengoptimuman yang bijak, iaitu mereka dengan cepat mencipta versi kod mesin yang tidak dioptimumkan pada permulaannya untuk memulakan pelaksanaan secepat mungkin.
- Di latar belakang, kod ini disusun semula semasa pelaksanaan pgm yang sudah berjalan.
- Dilakukan dalam pelbagai lelaran dan selepas setiap pengoptimuman kod yang tidak dioptimumkan ditukar dengan kod yang baru dioptimumkan tanpa menghentikan pelaksanaan kod. Ini menjadikan V8 begitu pantas.
- Semua penghuraian, penyusunan, pelaksanaan ini berlaku dalam beberapa utas khas di dalam JS Engine yang kami tidak boleh akses menggunakan kod kami berasingan sepenuhnya daripada utas utama yang menjalankan kod kami menggunakan tindanan panggilan.
- JS bukan lagi sekadar ditafsirkan l/g. Ia mempunyai kompilasi JIT yang menjadikannya lebih pantas daripada l/gs yang ditafsirkan.
JS Runtime = JS Engine + Web API + C/B Queue
- JS Runtime: Bekas termasuk semua perkara yang kita perlukan untuk menggunakan JS.
- Nadi mana-mana masa jalan JS ialah Enjin JS.
- Tanpa Enjin JS, tiada masa jalan justeru tiada JS langsung.
- Enjin JS sahaja tidak mencukupi, kami memerlukan akses kepada API Web seperti DOM, Ambil, Pemasa dll.
- API Web: Kefungsian disediakan kepada enjin mengikut masa jalan, tetapi bukan sebahagian daripada enjin JS. Cth. objek tetingkap dalam penyemak imbas, objek global dalam nod.
- Baris Gilir Panggilan Balik ialah struktur data yang mengandungi semua fungsi sedia untuk dilaksanakan. Cth. klik, pemasa, data dll
- Fns pengendali acara DOM juga dipanggil sebagai fns panggil balik.
- Apabila tindanan Panggilan kosong, fn panggil balik dialihkan daripada baris gilir C/B ke tindanan Panggilan untuk pelaksanaan.
- Pemeriksaan & peralihan berterusan dilakukan oleh Gelung Acara.
- Gelung peristiwa ialah sesuatu yang membolehkan JS mempunyai model konkurensi tidak menyekat.
- Untuk nod, kami tidak mempunyai API Web yang disediakan oleh penyemak imbas. Kami mempunyai sesuatu yang dipanggil sebagai pengikatan C++ & kumpulan benang.
Bagaimana Kod JS dilaksanakan pada Tindanan Panggilan
- JS mempunyai urutan pelaksanaan tunggal, oleh itu hanya boleh melakukan perkara pada satu masa. Oleh itu, tiada multiasking dalam JS.
- API disediakan oleh persekitaran, tetapi bukan bahagian bahasa. Cth. API Web seperti Pemasa, Ambil, DOM, Geolokasi dll.
- Baris Gilir Panggilan Balik: Sedia untuk dilaksanakan panggilan balik fns yang dilampirkan pada beberapa acara yang telah berlaku.
- Setiap kali tindanan panggilan kosong, gelung acara memindahkan panggilan balik dari calback ke baris gilir ke tindanan panggilan untuk pelaksanaan.
- Gelung acara ialah bahagian penting yang menjadikan gelagat Async dalam JS mungkin.
- Model Concurrency: Cara l/g mengendalikan berbilang perkara yang berlaku pada masa yang sama.
- Bahagian penting JS Runtime:
- Timbunan Panggilan
- API Web
- Baris Gilir Panggilan Balik
- Gelung acara
- Semua yang berkaitan dengan DOM adalah sebahagian daripada API Web, bukan JS.
- Pemuatan imej berlaku dalam cara tidak segerak, sekiranya ia berada dalam cara segerak maka ia akan menyekat iaitu bukan pada utas utama, sebaliknya persekitaran API Web.
- Semua pendengar acara, .then() dll berfungsi dalam persekitaran API WEb dan bukan pada timbunan panggilan.
- Fn panggilan balik diletakkan dalam baris gilir panggilan balik menunggu untuk dilaksanakan pada tindanan panggilan.
- Baris gilir panggilan balik adalah seperti senarai tugasan yang perlu diselesaikan oleh tindanan panggilan.
- Tempoh yang dinyatakan ialah kelewatan minimum sebelum pelaksanaan, dan bukan masa untuk pelaksanaan.
- Baris gilir panggilan balik juga mengandungi panggilan balik yang datang daripada acara DOM, klik, tekan kekunci dsb. Acara DOM bukan gelagat async, tetapi mereka menggunakan baris gilir panggil balik untuk pelaksanaannya.
- Gelung acara terus menyemak baris gilir panggil balik sehingga kosong. Setiap panggilan balik yang diletakkan pada tindanan panggilan dipanggil sebagai tanda gelung peristiwa.
- Gelung acara mengatur keseluruhan masa jalan JS.
- JS sendiri tidak mempunyai masa kerana kod Async tidak dilaksanakan dalam enjin. Ia adalah masa jalan yang mengurus gelagat async dan gelung acara yang menentukan panggilan balik yang hendak dilaksanakan.
- Timbunan Enjin atau Panggilan hanya melaksanakan kod yang diberikan kepadanya.
- Apabila imej hendak dimuatkan, pendengar acara terus menunggu dalam persekitaran API Web sehingga acara pemuatan dimatikan. Apabila ia dicetuskan, maka hanya ia pergi ke baris gilir panggil balik sebagai panggilan balik fn menunggu gilirannya untuk dilaksanakan pada tindanan panggilan.
Barisan Microtask:
- Panggilan balik daripada Promises tidak pergi ke baris gilir panggil balik, ia pergi ke baris gilir microtask.
- Baris gilir ini mempunyai keutamaan yang lebih tinggi berbanding baris gilir panggil balik.
- Gelung peristiwa menyemak baris gilir ini dahulu, melaksanakan semua tugasnya dahulu, kemudian pergi ke baris gilir panggil balik untuk pelaksanaan.
- Panggil balik pada janji dipanggil microtasks, oleh itu ia dipanggil microtask queue. Terdapat microtasks lain juga, tetapi tidak relevan di sini setakat ini. Gelung peristiwa menentukan apabila setiap panggilan balik dilaksanakan. Ia memberikan keutamaan yang lebih tinggi kepada microtask berbanding dengan baris gilir panggil balik
- Microtasks boleh memotong sebaris sebelum semua baris gilir panggil balik biasa yang lain.
- Promise.resolve() : mencipta janji yang diselesaikan serta-merta, dan nilai kejayaannya diluluskan di dalamnya sebagai hujah. maka() panggil balik dipanggil dengan nilai diselesaikan sebagai argumen.
console.log("Direct simple console BEGIN");
setTimeout(() => console.log("Text from Timer"),0);
Promise.resolve("Text from Promise").then(res => console.log(res));
console.log("Direct simple console END");
Order of Output:
Direct simple console BEGIN
Direct simple console END
Text from Promise
undefined
Text from Timer
Salin selepas log masuk
- Baris gilir tugasan mikro malah boleh menyebabkan baris gilir panggil balik kebuluran juga jika terdapat banyak tugasan mikro di dalamnya atau tugasan mikro yang memakan masa.
console.log("Direct simple console BEGIN");
setTimeout(() => console.log("Text from Timer"),0);
Promise.resolve("Text from Promise1").then(res => console.log(res));
Promise.resolve("Text from Promise2").then(res => {
for(let i=0; i<5000; i++)
console.log(res);
});
console.log("Direct simple console END");
Salin selepas log masuk
Atas ialah kandungan terperinci Enjin JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!