Harap baca kode berikut dan tebak hasil eksekusi:
var start = tanggal baru; setTimeout (function () {console.log ('waktu berlalu:'+(tanggal baru - mulai)+'msec');}, 200); while (Tanggal Baru - Mulai <1000) {} console.log (1); function dosoming () {setTimeout (function () {console.log ('waktu berlalu lagi:'+(tanggal baru - mulai)+'msec');}, 10);} dosoming (); while (tanggal baru - mulai <2000) {} console.log (2);ternyata:
Output setelah sekitar 1 detik: 1,
Setelah sekitar 1 detik, outputnya adalah: 2.
Kemudian segera output: waktu berlalu: 2002 milidetik
Output terakhir: Waktu berlalu lagi: 2003 milidetik
Apakah kamu sudah menebaknya kan?
Di sini, semua fungsi yang menunda eksekusi dengan SetTimeout didorong ke akhir sebelum eksekusi;
Prinsipnya adalah sebagai berikut:
Di lingkungan browser yang ada, mesin eksekusi JavaScript adalah satu utas. Pernyataan dan metode utas utama akan memblokir menjalankan tugas waktu. Di luar mesin eksekusi Javascript, ada antrian tugas. Ketika metode setTimeout () dipanggil dalam kode, metode penundaan terdaftar akan digantung ke modul lain di kernel browser untuk diproses. Ketika metode penundaan mencapai kondisi pemicu, yaitu, waktu tunda set mencapai set, modul akan menambahkan metode yang akan dieksekusi ke antrian tugas modul. Proses ini tidak tergantung pada utas utama mesin eksekusi. Mesin eksekusi akan mengekstrak tugas dari antrian tugas modul secara berurutan untuk dieksekusi ketika metode utas utama dieksekusi dan mencapai keadaan idle. Waktu selama periode ini mungkin lebih besar dari waktu tunda yang ditetapkan saat mendaftarkan tugas;
Ketika browser menganggur, ia akan terus -menerus mencoba mengekstrak tugas dari antrian tugas modul, yang disebut model loop peristiwa;
Mari kita lihat kembali kode sebelumnya. Metode penundaan penundaan kedua () adalah 10 milidetik, yang dipicu lebih awal dari yang pertama! Mengapa hasil eksekusi di belakang? Because it was blocked by the previous code for about 1000.5~1001 milliseconds (depending on the browser's processing speed), when it hangs to the processing module and when the trigger time is added to the task queue, the first setTimeout() delay method has long been added to the module's task team, and the main engine thread is obtained in order, so, you should understand, right?
Sekarang, jika Anda mengubah hal di atas (tanggal baru - mulai <1000) {} ke while (tanggal baru - mulai <189) {} atau while (tanggal baru - mulai <190) {}, apa hasilnya? Saya tidak akan banyak bicara! Segarkan peramban masing -masing 20 kali dan lihat hasilnya sendiri!
Metode setInterval () dan setTimeout () memiliki status yang sama. Ketika metode setInterval () dipanggil, metode penundaan terdaftar digantung pada modul untuk diproses. Setiap kali waktu pemicu tiba, metode yang akan dieksekusi ditambahkan ke antrian tugas sekali;
Mari kita lihat sintaksis setTimeout:
var timeId = window.setTimeout (func, delay, [param1, param2, ...]);
var timeId = window.setTimeout (kode, tunda);
setTimeout dan setInterval adalah metode objek jendela (jendela dapat dihilangkan). Parameter opsional kedua (tidak didukung oleh IE9 dan versi lama) adalah parameter yang diteruskan ke FUNC. Setiap kali mereka dipanggil, ID numerik akan dikembalikan (hanya angka yang dicetak di browser, tetapi saya mencetaknya di Webstorm dan menemukan bahwa itu sebenarnya adalah objek dengan banyak atribut). ID ini mempertahankan informasi yang relevan dari setTimeout atau setInterval yang sesuai, dan terutama digunakan untuk menghapus (atau menutup) mereka di modul tengah dan antrian tugas (menggunakan metode ClearTimeout (ID) dan ClearInterVal (ID)).
Jika Anda perlu meneruskan parameter ke fungsi panggilan balik Anda, berikut ini adalah metode penulisan yang kompatibel dengan IE
if (document.all &&! window.setTimeout.ispolyfill) {var __nativest__ = window.setTimeout; window.setTimeout = fungsi (vcallback, ndelay, param1, param2, param3) {var aargs = array.prototype.slice.call (argumen, 2); return __nativest __ (vcallback instanceof function? function () {vcallback.Apply (null, aargs);}: vcallback, ndelay); }; window.setTimeout.ispolyfill = true;}Kesalahan umum terjadi saat menggunakan penutupan dalam satu loop
untuk (var i = 0; i <10; i ++) {setTimeout (function () {console.log (i);}, 1000);}Kode di atas akan menghasilkan angka 10 sepuluh kali. Mengapa? Penutup!
Ketika Console.log dipanggil, meskipun fungsi anonim mempertahankan referensi ke variabel eksternal i, loop untuk telah berakhir pada saat ini dan nilai i dimodifikasi menjadi 10.
Untuk mendapatkan hasil yang diinginkan, salinan variabel yang perlu saya buat di setiap loop.
Untuk mendapatkan nomor loop dengan benar, yang terbaik adalah menggunakan pembungkus anonim (sebenarnya apa yang biasanya kita sebut fungsi anonim yang dieksekusi sendiri).
untuk (var i = 0; i <10; i ++) {(function (e) {setTimeout (function () {console.log (e);}, 1000);}) (i);}Fungsi anonim eksternal akan segera dieksekusi dan saya akan digunakan sebagai parameternya. Pada saat ini, variabel E dalam fungsi akan memiliki salinan i.
Ketika fungsi anonim yang diteruskan ke SetTimeout dieksekusi, ia memiliki referensi ke E, dan nilai ini tidak akan diubah oleh loop.
Ada cara lain untuk melakukan pekerjaan yang sama; yaitu mengembalikan fungsi dari pembungkus anonim. Ini berfungsi sama dengan kode di atas.
untuk (var i = 0; i <10; i ++) {setTimeout ((function (e) {return function () {console.log (e);}}) (i), 1000)}Aplikasi penting lainnya: fungsi throttle dan function debounce
Silakan lihat beberapa informasi yang saya kumpulkan dari internet:
JavaScript - Fungsi Optimasi Kinerja Throttle dan Function Debounce
Tautan referensi:
https://developer.mozilla.org/zh-cn/docs/web/api/window/settimeout
http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout-said-the-event-loop-model/#prettyphoto
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.