jQuery文档初始化函数原理

在jQuery的脚本使用中,经常注册文档初始化函数,比如:$(function(){}); 那么这句话原理是什么呢?

原理一、把completed函数注册到文档加载的原生事件中

关键在这一句document.addEventListener("DOMContentLoaded", completed, false);

jQuery.ready.promise = function (obj) {
        if (!readyList) {

            // 如果没有,新建一个 Deferred 对象
            // Deferred 用于处理异步延时回调函数,也就是内部用于 ready 的一个异步队列
            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 : 在setTimeout中触发的函数, 一定会在DOM准备完毕后触发.(即是 DOMContentLoaded)
                setTimeout(jQuery.ready);

                // Standards-based browsers support DOMContentLoaded
                // 支持 DOMContentLoaded 的浏览器 (除去ie 6 7 8)
            } else if (document.addEventListener) {
                // Use the handy event callback
                // 当检测的 document.readyState 的值不为 complete 时, 用 readystatechange 监听 document.readyState 值的变化事件
                document.addEventListener("DOMContentLoaded", completed, false);

                // A fallback to window.onload, that will always work
                // 一种退而求其次的方法,确保一定会发生
                window.addEventListener("load", completed, false);

                // If IE event model is used
                // 如果是 IE 浏览器(6、7、8)
            } else {
                // Ensure firing before onload, maybe late but safe also for iframes
                document.attachEvent("onreadystatechange", completed);

                // A fallback to window.onload, that will always work
                window.attachEvent("onload", completed);

                // If IE and not a frame
                // continually check to see if the document is ready
                // 如果是 IE 且不是在 frame 中
                var top = false;

                try {
                    top = window.frameElement == null && document.documentElement;
                } catch (e) { }

                // 如果是IE并且不是iframe
                if (top && top.doScroll) {
                    // 这里有个立即执行函数 doScrollCheck()
                    (function doScrollCheck() {
                        if (!jQuery.isReady) {

                            try {
                                // Use the trick by Diego Perini
                                // http://javascript.nwbox.com/IEContentLoaded/
                                // Diego Perini 在 2007 年的时候,报告了一种检测 IE 是否加载完成的方式,使用 doScroll 方法调用
                                // 原理就是对于 IE 在非 iframe 内时,只有不断地通过能否执行 doScroll 判断 DOM 是否加载完毕
                                // 在上述中间隔 50 毫秒尝试去执行 doScroll,注意,由于页面没有加载完成的时候,调用 doScroll 会导致异常,所以使用了 try - catch 来捕获异常
                                // 直到DOM渲染结束了,这个时候 doScroll 方法不会抛出异常,然后就调用$.ready()
                                top.doScroll("left");
                            } catch (e) {
                                return setTimeout(doScrollCheck, 50);
                            }

                            // detach all dom ready events
                            detach();

                            // and execute any waiting functions
                            jQuery.ready();
                        }
                    })();
                }
            }
        }
        // 函数返回的是deferred对象,这就可以加上链式操作了
        // 可以使用 .done .fail 等方法
        return readyList.promise(obj);

        // Populate the class2type map
    };


原理二、使用deferred对象管理队列方法

还是上面的代码,,注意到有这么一句:readyList = jQuery.Deferred();,这个readyList是闭包内的“全局变量”,在completed调用栈中也会使用到

原理三、completed函数触发后会触发readList的resolveWith方法进行触发

关键代码:readyList.resolveWith(document,[jQuery])进行触发deferred函数队列




/*注册文档就绪函数:$(function(){});*/
	/*
	首先下面几种写法都是一样的,最终都是jQuery(document).ready(function(){});
	$("#box").ready(function(){});
	$(function(){});
	
	jQuery(document).ready(fn);
		-->jQuery.ready.promise().done(fn);
			-->在promise方法中初始化readyList这是一个deferred对象
				添加dom加载完成事件"completed"
			-->执行readList.promise()的done方法注册dom加载完成方法
			
		当文档加载完成后触发了complete方法,这个方法中执行如下:
		-->移除dom加载事件中注册的complete方法
		-->执行jQuery.ready()方法
			-->调用readyList.resolveWith(document,[jQuery])进行触发deferred函数队列
	
	*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jackletter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值