โปรดอ่านรหัสต่อไปนี้และเดาผลการดำเนินการ:
var start = วันที่ใหม่; settimeout (function () {console.log ('เวลาผ่าน:'+(วันที่ใหม่ - เริ่มต้น)+'msec');}, 200); ในขณะที่ (วันที่ใหม่ - เริ่มต้น <1000) {} console.log (1); ฟังก์ชัน dosoming () {settimeout (ฟังก์ชัน () {console.log ('เวลาผ่านไปอีกครั้ง:'+(วันที่ใหม่ - เริ่มต้น)+'msec');}, 10);} dosoming (); ในขณะที่ (วันที่ใหม่ - เริ่ม <2000) {} console.log (2);กลับกลายเป็นว่า:
เอาท์พุทหลังจากประมาณ 1 วินาที: 1,
หลังจากนั้นประมาณ 1 วินาทีเอาต์พุตคือ: 2
จากนั้นเอาท์พุททันที: เวลาผ่านไป: 2545 มิลลิวินาที
เอาท์พุทล่าสุด: เวลาผ่านไปอีกครั้ง: 2546 มิลลิวินาที
คุณเดาได้ไหม?
ที่นี่ฟังก์ชั่นทั้งหมดที่ชะลอการดำเนินการโดย settimeout จะถูกผลักไปยังจุดสิ้นสุดก่อนการดำเนินการ;
หลักการมีดังนี้:
ในสภาพแวดล้อมของเบราว์เซอร์ที่มีอยู่แล้วเอ็นจิ้นการดำเนินการ JavaScript เป็นเธรดเดี่ยว คำสั่งและวิธีการของเธรดหลักจะบล็อกการทำงานของงานเวลา นอกเอ็นจิ้นการดำเนินการ JavaScript มีคิวงาน เมื่อมีการเรียกวิธี SetTimeOut () ในรหัสวิธีการหน่วงเวลาที่ลงทะเบียนจะถูกแขวนไว้กับโมดูลอื่น ๆ ในเคอร์เนลเบราว์เซอร์สำหรับการประมวลผล เมื่อวิธีการหน่วงเวลาถึงเงื่อนไขทริกเกอร์นั่นคือเวลาการหน่วงเวลาที่กำหนดถึงชุดโมดูลจะเพิ่มวิธีการที่จะดำเนินการกับคิวงานของโมดูล กระบวนการนี้เป็นอิสระจากเธรดหลักของเอ็นจิ้นการดำเนินการ เอ็นจิ้นการดำเนินการจะแยกงานออกจากคิวงานของโมดูลตามลำดับเพื่อดำเนินการเมื่อวิธีการเธรดหลักถูกดำเนินการและถึงสถานะที่ไม่ได้ใช้งาน เวลาในช่วงเวลานี้อาจมากกว่าเวลาล่าช้าเมื่อลงทะเบียนงาน
เมื่อเบราว์เซอร์ไม่ได้ใช้งานมันจะพยายามแยกงานออกจากคิวงานของโมดูลซึ่งเรียกว่าโมเดลลูปเหตุการณ์
ลองดูรหัสก่อนหน้า เวลาหน่วงของวิธีการล่าช้าครั้งที่สอง () หน่วงคือ 10 มิลลิวินาทีซึ่งถูกเรียกเร็วกว่าครั้งแรก! ทำไมผลการดำเนินการอยู่เบื้องหลัง? เพราะมันถูกบล็อกโดยรหัสก่อนหน้านี้ประมาณ 1,000.5 ~ 1001 มิลลิวินาที (ขึ้นอยู่กับความเร็วในการประมวลผลของเบราว์เซอร์) เมื่อมันแขวนอยู่กับโมดูลการประมวลผลและเมื่อเพิ่มเวลาทริกเกอร์ลงในคิวงานแรก
ตอนนี้ถ้าคุณเปลี่ยนไปข้างต้น (วันที่ใหม่ - เริ่มต้น <1,000) {} เป็นขณะที่ (วันที่ใหม่ - เริ่มต้น <189) {} หรือในขณะที่ (วันที่ใหม่ - เริ่มต้น <190) {} ผลลัพธ์คืออะไร? ฉันจะไม่พูดมาก! รีเฟรชเบราว์เซอร์ 20 ครั้งและดูผลลัพธ์ด้วยตัวเอง!
เมธอด setInterval () และ settimeout () มีสถานะเดียวกัน เมื่อมีการเรียกวิธีการ setInterval () วิธีการหน่วงเวลาที่ลงทะเบียนจะถูกแขวนไว้กับโมดูลสำหรับการประมวลผล เมื่อใดก็ตามที่เวลาทริกเกอร์มาถึงวิธีการที่จะดำเนินการจะถูกเพิ่มเข้าไปในคิวงานหนึ่งครั้ง
มาดูไวยากรณ์ของ Settimeout:
var timeid = window.settimeout (func, การหน่วงเวลา, [param1, param2, ... ]);
var timeid = window.settimeout (รหัสล่าช้า);
Settimeout และ SetInterval เป็นวิธีการของวัตถุหน้าต่าง (สามารถละเว้นหน้าต่าง) พารามิเตอร์ตัวเลือกที่สอง (ไม่รองรับโดย IE9 และรุ่นเก่า) คือพารามิเตอร์ที่ส่งผ่านไปยัง Func ทุกครั้งที่พวกเขาถูกเรียกว่า ID ตัวเลขจะถูกส่งคืน (เป็นเพียงตัวเลขที่พิมพ์ในเบราว์เซอร์ แต่ฉันพิมพ์ใน Webstorm และพบว่ามันเป็นวัตถุที่มีคุณลักษณะมากมาย) ID นี้เก็บรักษาข้อมูลที่เกี่ยวข้องของ settimeout หรือ setInterval ที่เกี่ยวข้องและส่วนใหญ่จะใช้เพื่อล้าง (หรือปิด) ในโมดูลกลางและคิวงาน (ใช้วิธีการ ClearTimeOut (ID) และ ClearInterval (ID))
หากคุณต้องการส่งพารามิเตอร์ลงในฟังก์ชันการโทรกลับของคุณต่อไปนี้เป็นวิธีการเขียนที่เข้ากันได้กับ IE
if (document.all &&! window.settimeout.ispolyfill) {var __nativest__ = window.settimeout; window.settimeout = ฟังก์ชั่น (vCallback, ndelay, param1, param2, param3) {var aargs = array.prototype.slice.call (อาร์กิวเมนต์, 2); return __NatiVest __ (vCallback instanceof function? function () {vcallback.apply (null, aargs);}: vcallback, ndelay); - window.settimeout.ispolyfill = true;}ข้อผิดพลาดทั่วไปเกิดขึ้นเมื่อใช้การปิดในลูป
สำหรับ (var i = 0; i <10; i ++) {settimeout (function () {console.log (i);}, 1000);}รหัสข้างต้นจะส่งออกหมายเลข 10 สิบครั้ง ทำไม ปิด!
เมื่อเรียกว่า console.log แม้ว่าฟังก์ชั่นที่ไม่ระบุชื่อจะยังคงมีการอ้างอิงถึงตัวแปรภายนอก I แต่การวนรอบสิ้นสุดลงในเวลานี้และค่าของฉันได้รับการแก้ไขเป็น 10
เพื่อให้ได้ผลลัพธ์ที่ต้องการสำเนาของตัวแปรที่ฉันต้องสร้างในแต่ละลูป
เพื่อให้ได้หมายเลขลูปอย่างถูกต้องควรใช้เสื้อคลุมที่ไม่ระบุชื่อ (ที่จริงแล้วสิ่งที่เรามักจะเรียกฟังก์ชั่นที่ไม่ระบุชื่อด้วยตนเอง)
สำหรับ (var i = 0; i <10; i ++) {(ฟังก์ชั่น (e) {settimeout (function () {console.log (e);}, 1000);}) (i);}ฟังก์ชั่นที่ไม่ระบุชื่อภายนอกจะถูกดำเนินการทันทีและฉันจะถูกใช้เป็นพารามิเตอร์ ในเวลานี้ตัวแปร E ในฟังก์ชั่นจะมีสำเนาของ i
เมื่อฟังก์ชั่นที่ไม่ระบุชื่อผ่านไปยัง SettimeOut จะถูกดำเนินการจะมีการอ้างอิงถึง E และค่านี้จะไม่เปลี่ยนแปลงโดยลูป
มีอีกวิธีหนึ่งในการทำงานเดียวกัน นั่นคือการส่งคืนฟังก์ชั่นจากเสื้อคลุมที่ไม่ระบุชื่อ วิธีนี้ใช้งานได้เช่นเดียวกับรหัสข้างต้น
สำหรับ (var i = 0; i <10; i ++) {settimeout ((ฟังก์ชั่น (e) {return function () {console.log (e);}}) (i), 1000)}แอปพลิเคชั่นที่สำคัญอีกอย่างหนึ่ง: ฟังก์ชั่นเค้นและฟังก์ชั่น debounce
โปรดดูข้อมูลบางอย่างที่ฉันรวบรวมจากอินเทอร์เน็ต:
JavaScript - ฟังก์ชั่นการเพิ่มประสิทธิภาพประสิทธิภาพการทำงานและฟังก์ชั่น debounce ฟังก์ชั่น
ลิงค์อ้างอิง:
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
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น