jQuery中的ready事件原型,在这里提取出来便于理解,代码+注释 如下:
// 事件队列 var EventQueue = null; // 是否已经执行过了,只执行一次 var isFire = false; //添加ready事件 function addReadyEvent(fn){ if(!EventQueue) EventQueue = []; if(document.readyState == 'complete'){ fn(); }else{ EventQueue.push(fn); } } // 触发ready事件 function fireReadyEvent(){ if(!isFire){ var fn,i=0; if(EventQueue){ while(fn = EventQueue[i]){ fn(); i++; } EventQueue = null; } isFire = true; } } // 绑定ready事件 function bindReady(){ if(document.addEventListener){ // 标准浏览器DOM加载完毕后执行队列,并卸载事件 document.addEventListener('DOMContentLoaded',unbindReady,false); // 确保会执行 window.addEventListener('load',fireReadyEvent,false); }else if(document.attachEvent){ // IE浏览器加载事件变化的时候执行unbindReady document.attachEvent('onreadystatechange',unbindReady); // 确保会执行 window.attachEvent('onload',fireReadyEvent); } var toplevel = false; // 是否顶层对象 try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { // IE通过判断doScroll,在onreadystatechange = 'complete' 之前执行 doScrollCheck(); } } function doScrollCheck() { if ( isFire ) { return; } try { // IE下加载BODY后即可正常执行doScroll() document.documentElement.doScroll("left"); } catch( error ) { // 循环执行doScroll setTimeout( doScrollCheck, 1 ); return; } // doScroll成功后执行队列 fireReadyEvent(); } // 移除绑定事件并执行队列 function unbindReady(){ if(document.addEventListener){ //标准浏览器支持DOMContentLoaded事件 document.removeEventListener('DOMContentLoaded',unbindReady,false); fireReadyEvent(); }else if(document.attachEvent){ if(document.readyState === 'complete'){ // IE浏览器支持complete事件 document.detachEvent('onreadystatechange',unbindReady); fireReadyEvent(); } } } bindReady(); window.onload = function(){ console.log('LOAD加载完毕!'); } addReadyEvent(function(){ console.log('DOM加载完毕1!'); }); addReadyEvent(function(){ console.log('DOM加载完毕22!'); }) addReadyEvent(function(){ console.log('DOM加载完毕33!'); })