还记不记得jQuery初始化函数jQuery.fn.init中有这样是一个分支

//document ready简便写法$(function(){…})
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}

  所以$(fn)===$(document).ready(fn)。

  来看一下jQuery.fn.ready的源码

ready: function( fn ) {
// Add the callback
jQuery.ready.promise().done( fn ); return this;
}

  很明显在jQuery.ready.promise函数中设置了延时,当延时对象解决的时候执行fn函数。

  主要的处理流程:

  创建一个延时对象,并将文档准备好后的处理事件添加到该延时对象成功事件列表上。

jQuery.ready.promise = function( obj ) {
  if ( !readyList ) {
    readyList = jQuery.Deferred();     ...   }
return readyList.promise( obj );
}

  添加文档准备状态的监听函数(jQuery.ready.promise函数片段)

    //标准浏览器支持DOMContentLoaded事件
} else if ( document.addEventListener ) {
//绑定DOMContentLoaded事件和响应函数,响应函数会解决延时
document.addEventListener( "DOMContentLoaded", completed, false ); //回退到window.onload事件绑定,所有的浏览器都支持
window.addEventListener( "load", completed, false ); //如果是IE事件模型
} else {
//确保在onload之前执行延时,可能时间比较迟,但是对于iframes来说比较安全
document.attachEvent( "onreadystatechange", completed ); //回退到window.onload事件绑定,所有的浏览器都支持
window.attachEvent( "onload", completed ); //如果IE并且不是一个frame
//不断地检查,看是否该文件已准备就绪
var top = false;
try {
top = window.frameElement == null && document.documentElement;
} catch(e) {}
if ( top && top.doScroll ) {
(function doScrollCheck() {
if ( !jQuery.isReady ) {
try {
// Use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
top.doScroll("left");
} catch(e) {
return setTimeout( doScrollCheck, 50 );
} //移除之前绑定的事件
detach(); //执行延迟
jQuery.ready();
}
})();
}
}

  一旦监听到文档准备完成,则调用jQuery.ready执行延时对象的成功回调列表:即所有通过jQuery.ready(fn)【或jQuery(fn)】方式添加的函数fn。

//ready事件处理函数
completed = function( event ) {
// readyState === "complete"在老版本IE上适用
if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
detach();
jQuery.ready();
}
},
//清除ready事件绑定
detach = function() {
if ( document.addEventListener ) {
document.removeEventListener( "DOMContentLoaded", completed, false );
window.removeEventListener( "load", completed, false ); } else {
document.detachEvent( "onreadystatechange", completed );
window.detachEvent( "onload", completed );
}
};
//处理当DOM准备完成
jQuery.ready: function( wait ) {      
...        
//设置DOM已经准备好的标志      
jQuery.isReady = true;   
...   
//执行绑定的延时事件   
readyList.resolveWith( document, [ jQuery ] );   
//触发任何绑定的就绪事件   
if ( jQuery.fn.trigger ) {     
jQuery( document ).trigger("ready").off("ready");   
}
}

  整个过程就是如此。其中有一些小的知识点整理一下。

a. 文档加载状态document.readyState


  document.readyState用来判断文档加载状态,是一个只读属性,可能的值有:

  0-uninitialized:XML 对象被产生,但没有任何文件被加载。
  1-loading:加载程序进行中,但文件尚未开始解析。
  2-loaded:部分的文件已经加载且进行解析,但对象模型尚未生效。
  3-interactive:仅对已加载的部分文件有效,在此情况下,对象模型是有效但只读的。
  4-complete:文件已完全加载,代表加载成功。

  实例:

document.onreadystatechange = stateChange;//当页面加载状态改变的时候执行这个方法.
function stateChange() {   
  if(document.readyState == "complete"){ //当页面加载状态为完全结束时进入     
    alert("文档加载成功")   
  }
}

  但是,老版本的Firefox并不支持document.readyState【最新的Firefox已经支持了】。所以想要兼容所有浏览器监听文档准备完成分两种情况来处理:

  - 标准浏览器使用addEventListener添加DOMContentLoaded和load监听,任何一个事件被触发即可

  - 老版本IE浏览器使用attachEvent添加onreadystatechange和onload来监听,任何一个被触发,并且onreadystatechange时document.readyState === "complete"即可。

  jQuery的处理也就是如此了

jQuery.ready.promise = function(){
  ...
  //标准浏览器支持DOMContentLoaded事件
  else if ( document.addEventListener ) {
//绑定DOMContentLoaded事件和响应函数,响应函数会解决延时
document.addEventListener( "DOMContentLoaded", completed, false ); //回退到window.onload事件绑定,所有的浏览器都支持
window.addEventListener( "load", completed, false ); //如果是IE事件模型
} else {
//确保在onload之前执行延时,可能时间比较迟,但是对于iframes来说比较安全
document.attachEvent( "onreadystatechange", completed ); //回退到window.onload事件绑定,所有的浏览器都支持
window.attachEvent( "onload", completed );
       ...
  }
}
//ready事件处理函数
completed = function( event ) {
// readyState === "complete"在老版本IE上适用
if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
detach();
jQuery.ready();
}
}

  

b.doScroll检测文档加载完成


  这是Diego Perini 发现的一种检测IE是否加载完成的方式。详细链接

  原理是当页面 DOM 未加载完成时调用 doScroll 方法时会产生异常。那么不断的取检测异常是否发生就可以知道文档有没有加载完成。当没有发生异常,表明文档加载完成了。

                (function doScrollCheck() {
if ( !jQuery.isReady ) {
try {
// Use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
top.doScroll("left");
} catch(e) {
return setTimeout( doScrollCheck, 50 );
} //移除之前绑定的事件
detach(); //执行延迟
jQuery.ready();
}
})();

  如果觉得本文不错,请点击右下方【推荐】!

jQuery-1.9.1源码分析系列(六) 延时对象应用——jQuery.ready的更多相关文章

  1. jQuery源码分析系列(一)初识jQuery

    一个工厂 (function(global, factory){ "use strict" // operation_1 })(typedef window !== "u ...

  2. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  3. [转]jQuery源码分析系列

    文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...

  4. jQuery源码分析系列(转载来源Aaron.)

    声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...

  5. jQuery源码分析系列——来自Aaron

    jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...

  6. jquery2源码分析系列

    学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...

  7. jQuery-1.9.1源码分析系列完毕目录整理

    jQuery 1.9.1源码分析已经完毕.目录如下 jQuery-1.9.1源码分析系列(一)整体架构 jQuery-1.9.1源码分析系列(一)整体架构续 jQuery-1.9.1源码分析系列(二) ...

  8. MyCat源码分析系列之——结果合并

    更多MyCat源码分析,请戳MyCat源码分析系列 结果合并 在SQL下发流程和前后端验证流程中介绍过,通过用户验证的后端连接绑定的NIOHandler是MySQLConnectionHandler实 ...

  9. MyCat源码分析系列之——SQL下发

    更多MyCat源码分析,请戳MyCat源码分析系列 SQL下发 SQL下发指的是MyCat将解析并改造完成的SQL语句依次发送至相应的MySQL节点(datanode)的过程,该执行过程由NonBlo ...

  10. MyCat源码分析系列之——BufferPool与缓存机制

    更多MyCat源码分析,请戳MyCat源码分析系列 BufferPool MyCat的缓冲区采用的是java.nio.ByteBuffer,由BufferPool类统一管理,相关的设置在SystemC ...

随机推荐

  1. VS2012 2013 显示查找功能 无法具体定位 解决方法

    问题的现象:通过使用 Ctrl + Shift + F 也就是Find In Files功能,使用之后只能显示统计结果,不显示具体行.如下图     regedit 中在注册表中查找:HKEY_CLA ...

  2. androidannotations 简单复制与点击事件(1)

    现在最火的android开发框架 简单描述一下 这一篇简单描述寻找控件以及事件的使用 1.该方法可以不用写setconteview @EActivity(R.layout.activity_main) ...

  3. CYQ.Data V5 数据库读写分离功能介绍

    前言 好多年没写关于此框架的新功能的介绍了,这些年一直在默默地更新,从Nuget上的记录就可以看出来: 这几天在看Java的一些东西,除了觉的Java和.NET的相似度实在太高之外,就是Java太原始 ...

  4. Centos 使用YUM安装MariaDB

    1.在 /etc/yum.repos.d/ 下建立 MariaDB.repo,内容如下: [azureuser@mono etc]$ cd /etc/yum.repos.d [azureuser@mo ...

  5. 递归算法经典实例小结(C#实现)

     一 .递归算法简介 在数学与计算机科学中,递归是指在函数的定义中使用函数自身的方法. 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往 ...

  6. java中文乱码解决之道(八)-----解决URL中文乱码问题

    我们主要通过两种形式提交向服务器发送请求:URL.表单.而表单形式一般都不会出现乱码问题,乱码问题主要是在URL上面.通过前面几篇博客的介绍我们知道URL向服务器发送请求编码过程实在是实在太混乱了.不 ...

  7. JavaScript常见原生DOM操作API总结

    [TOC] 最近面试的时候被这个问题给卡了,所以抽时间好好复习一下. 几种对象 Node Node是一个接口,中文叫节点,很多类型的DOM元素都是继承于它,都共享着相同的基本属性和方法.常见的Node ...

  8. Android学习第三天-签名常用命令

    由于怕篇幅过长,所以把这个打包常用命令分开成两篇博文来进行讲解,下面我们直接进入主题吧. 8.keytool 这是我们JDK自带的密钥和证书管理工具 命令: -certreq 生成证书请求 -chan ...

  9. Spark的持久化简记

    摘要: 1.spark 提供的持久化方法 2.Spark的持久化级别 3.如何选择一种最合适的持久化策略 内容: 1.spark 提供的持久化方法 如果要对一个RDD进行持久化,只要对这个RDD调用c ...

  10. 【ssh信任关系】解决信任关系不生效问题

    配置的时候遇见点问题,发现即便将id_rsa.pub拷贝到了另一台机器上,信任也没有建立起来. 原因是另外一台机器上目录权限不对,可以通过su root后观察/var/log/message里的日志信 ...