先来看一下window.onload 和$(document).ready()的区别,window.onload是等整个页面全部加载完毕,而$(document).ready()只是等待DOM加载完毕,举个例子,比如img标签,window.onload是等图片加载完毕,而DOM加载只是加载这个DOM标签,不必等图片加载完毕。实际上jQuery调用的是DOMContentLoaded事件。
我们来看一下这样的用法:
$(function(){
console.log("document ready");
});
让我们来回顾一下,$()即调用jQuery方法,在jQuery源码刚开始的地方我们就可以看到:
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
},
该方法调用了jQuery.fn.inti构造函数,即原型对象中的init方法,该方法会判断传入的参数,如果是一个函数,实际上调用的是$(document).ready(),所以$(function(){})和$(document).ready(function(){})是一样的
else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector ); //在源码中有这样的赋值,rootjQuery = jQuery(document);
}
在jQuery的原型对象中可以找到ready函数,这实际上是每个jQuery对象的方法,从调用方式$(document).ready()中也可以看出来这是兑现方法。这个方法的源码是这样的:
ready: function( fn ) {
// Add the callback
jQuery.ready.promise().done( fn );
return this;
},
jQuery.ready.promise = function( obj ) {
if ( !readyList ) {
readyList = jQuery.Deferred();
// Catch cases where $(document).ready() is called after the browser event has already occurred.
// we once tried to use readyState "interactive" here, but it caused issues like the one
// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
setTimeout( jQuery.ready );
} else {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", completed, false );
// A fallback to window.onload, that will always work
window.addEventListener( "load", completed, false );
}
}
return readyList.promise( obj );
};
在else中,为两个事件都添加了complete方法,DOMContentLoaded 和load事件,按理说DOMContentLoaded事件应该是在load之前就被触发,仍然监测这两个事件主要是为了确保在有些浏览器采用缓存策略的情况下仍可以正常触发complet方法,有些浏览器如火狐会缓存load事件,导致load事件在DOMContentLoaded事件之前触发,同时绑定这两个事件可以保证complete函数最快被触发。
我们来看一下complet函数,这个函数是在jQuery作用域里定义的一个全局的函数。在代码刚开始的地方:
completed = function() {
document.removeEventListener( "DOMContentLoaded", completed, false );
window.removeEventListener( "load", completed, false );
jQuery.ready();
};
这个函数取消了complete函数的绑定以确保complet函数只会执行一次,最终实际上是调用了jQuery.ready这个工具方法,这与jQuery.ready.promise方法中readyState为complete情况下是一样的,也就是说
可以看到不管是if还是else,最终都会调用jQuery.ready这个方法,该方法是通过$.extend()扩展的一个工具方法: