يرجى قراءة الرمز التالي وتخمين نتيجة التنفيذ:
var start = new date ؛ setTimeout (function () {console.log ('time passes:'+(تاريخ جديد - ابدأ)+'msec') ؛} ، 200) ؛ بينما (تاريخ جديد - ابدأ <1000) {} console.log (1) ؛ function dosoming () {setTimeOut (function () {console.log ('الوقت يمر مرة أخرى:'+(تاريخ جديد - start)+'msec') ؛} ، 10) ؛} dosoming () ؛ بينما (تاريخ جديد - ابدأ <2000) {} console.log (2) ؛تحول:
الإخراج بعد حوالي 1 ثانية: 1 ،
بعد حوالي 1 ثانية ، الإخراج هو: 2.
ثم الإخراج على الفور: مرر الوقت: 2002 ميلي ثانية
الإخراج الأخير: مرت الوقت مرة أخرى: 2003 مللي ثانية
هل خمنت ذلك صحيح؟
هنا ، يتم دفع جميع الوظائف التي تأخر تنفيذها بواسطة SetTimeout إلى النهاية قبل التنفيذ ؛
المبدأ كما يلي:
في بيئة المتصفح الحالية ، يكون محرك تنفيذ JavaScript متاحًا. ستمنع عبارات وطرق الخيط الرئيسي تشغيل مهام التوقيت. خارج محرك تنفيذ JavaScript ، هناك قائمة انتظار مهمة. عندما يتم استدعاء طريقة setTimeOut () في الكود ، سيتم تعليق طريقة التأخير المسجلة إلى وحدات أخرى في kernel متصفح للمعالجة. عندما تصل طريقة التأخير إلى شرط الزناد ، أي وقت تأخير المجموعة يصل إلى المجموعة ، ستضيف الوحدة النمطية الطريقة التي سيتم تنفيذها إلى قائمة انتظار المهمة للوحدة. هذه العملية مستقلة عن الخيط الرئيسي لمحرك التنفيذ. سيقوم محرك التنفيذ باستخراج المهام من قائمة انتظار المهمة للوحدة بالتسلسل لتنفيذها عند تنفيذ طريقة الخيط الرئيسي والوصول إلى حالة الخمول. قد يكون الوقت خلال هذه الفترة أكبر من وقت التأخير عند تسجيل المهمة ؛
عندما يكون المتصفح خاملاً ، سيحاول باستمرار استخراج المهام من قائمة انتظار مهمة الوحدة ، والتي تسمى نموذج حلقة الحدث ؛
دعونا نلقي نظرة على الكود السابق. تبلغ وقت التأخير لطريقة التأخير الثانية SetTimeOut () 10 مللي ثانية ، والتي يتم تشغيلها قبل ذلك من أول واحد! لماذا هي نتيجة التنفيذ وراء؟ نظرًا لأنه تم حظره بواسطة الكود السابق لحوالي 1000.5 ~ 1001 مللي ثانية (اعتمادًا على سرعة معالجة المتصفح) ، عندما يتم تعليقه إلى وحدة المعالجة وعندما تتم إضافة وقت الزناد إلى قائمة انتظار المهمة ، تتم إضافة طريقة تأخير TTITYOT () الأولى منذ فترة طويلة إلى فريق مهمة الوحدة النمطية ، ويتم الحصول على خيط المحرك الرئيسي بالترتيب ، لذلك ، يجب أن تفهم ،؟
الآن ، إذا قمت بتغيير ما سبق بينما (تاريخ جديد - ابدأ <1000) {} إلى (تاريخ جديد - ابدأ <189) {} أو بينما (تاريخ جديد - ابدأ <190) {} ، ما هي النتيجة؟ لن أقول الكثير! قم بتحديث المتصفح 20 مرة لكل منهما وشاهد النتائج بنفسك!
طريقة setInterval () و setTimeOut () لها نفس الحالة. عندما يتم استدعاء طريقة setInterval () ، يتم تعليق طريقة التأخير المسجلة إلى الوحدة النمطية للمعالجة. عند وصول وقت الزناد ، تتم إضافة الطريقة التي سيتم تنفيذها إلى قائمة انتظار المهمة مرة واحدة ؛
دعونا نلقي نظرة على بناء جملة Settimeout:
var timeid = window.settimeout (func ، delay ، [param1 ، param2 ، ...]) ؛
var timeid = window.settimeout (رمز ، تأخير) ؛
SetTimeout و SetInterval هي طرق لكائنات النوافذ (يمكن حذف النافذة). المعلمات الاختيارية الثانية (غير مدعومة من قبل IE9 والإصدارات القديمة) هي معلمات تم تمريرها إلى FUNC. في كل مرة يتم استدعاؤها ، سيتم إرجاع معرف رقمي (إنه مجرد رقم مطبوع في المتصفح ، لكنني قمت بطباعته في عاصفة الويب ووجدت أنه في الواقع كائن له العديد من السمات). يحافظ هذا المعرف على المعلومات ذات الصلة الخاصة بـ SetTimeOut المقابلة أو setInterval ، ويستخدم بشكل أساسي لمسحها (أو إغلاقها) في الوحدة الوسطى وقائمة انتظار المهمة (باستخدام الأساليب ClearTimeOut (ID) و ClearInterval (ID)).
إذا كنت بحاجة إلى تمرير معلمة في وظيفة رد الاتصال ، فإن ما يلي هو طريقة الكتابة المتوافقة مع IE
if (document.all &&! window.settimeout.ispolyfill) {var __nativest__ = window.settimeout ؛ Window.SettImeout = function (vcallback ، ndelay ، param1 ، param2 ، param3) {var aargs = array.prototype.slice.call (الوسائط ، 2) ؛ return __nativest __ (vcallback extryof 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 ، فقد انتهت الحلقة لـ For في هذا الوقت وتم تعديل قيمة I إلى 10.
للحصول على النتيجة المرجوة ، يجب إنشاء نسخة من المتغير الذي يجب أن يتم إنشاؤه في كل حلقة.
من أجل الحصول على رقم الحلقة بشكل صحيح ، من الأفضل استخدام غلاف مجهول (في الواقع ما نسميه عادةً وظائف مجهولة المصدر).
لـ (var i = 0 ؛ i <10 ؛ i ++) {(function (e) {setTimeOut (function () {console.log (e) ؛} ، 1000) ؛}) (i) ؛}سيتم تنفيذ الوظيفة الخارجية المجهولة على الفور وسيتم استخدامها كمعلمة لها. في هذا الوقت ، سيكون للمتغير E في الوظيفة نسخة من i.
عندما يتم تنفيذ الوظيفة المجهولة التي يتم تمريرها إلى setTimeout ، فإنها تحتوي على إشارة إلى E ، ولن يتم تغيير هذه القيمة بواسطة الحلقة.
هناك طريقة أخرى للقيام بنفس الوظيفة ؛ وهذا هو لإرجاع وظيفة من غلاف مجهول. هذا يعمل نفس الرمز أعلاه.
لـ (var i = 0 ؛ i <10 ؛ i ++) {setTimeOut ((function (e) {return function () {console.log (e) ؛}}) (i) ، 1000)}تطبيق مهم آخر: خنق الوظيفة والوظيفة debounce
يرجى الاطلاع على بعض المعلومات التي جمعتها من الإنترنت:
JavaScript - وظيفة تحسين الأداء الخانق ودالة الدالة
الرابط المرجعي:
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 أكثر.