jQuery源码学习(5)--$(fn)

版本:jquery1.10.2

时间:2014-02-25

已知$(fn)使用Deferred对象实现,你觉得实现$(fn)的步骤是什么呢?

1.给DOM加载绑定事件回调函数
2.将fn添加到延迟对象Deferred中
3.DOM加载完毕,回调函数调用Deferred.resolveWith(),执行回调函数fn

有点事后诸葛亮的意思哎!不过想想还能怎么做呢!

 

1
init 函数中 rootjQuery.ready( selector );
1
2
3
4
ready: function( fn ) {
    jQuery.ready.promise().done( fn );//给DOM加载绑定回调函数,将fn注册进Deferred对象中,在这一句代码完成了。
    return this;
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//给DOM的加载绑定回调函数completed,详细的分析可以看看这篇文字http://www.nowamagic.net/javascript/js_OnDomReady.php
 
jQuery.ready.promise = function( obj ) {
    if ( !readyList ) {
        readyList = jQuery.Deferred();
        if ( document.readyState === "complete" ) {
            setTimeout( jQuery.ready );
        } else if ( document.addEventListener ) {
            document.addEventListener( "DOMContentLoaded", completed, false );
            window.addEventListener( "load", completed, false );
        } else {
            document.attachEvent( "onreadystatechange", completed );
            window.attachEvent( "onload", completed );
            var top = false;
            try {
                top = window.frameElement == null && document.documentElement;
            } catch(e) {}
 
            if ( top && top.doScroll ) {
                (function doScrollCheck() {
                    if ( !jQuery.isReady ) {
                        try {
                            top.doScroll("left");
                        } catch(e) {
                            return setTimeout( doScrollCheck, 50 );
                        }
                        detach();
                        jQuery.ready();
                    }
                })();
            }
        }
    }
    return readyList.promise( obj );
}

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function completed( event ) {
    if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
        detach();
        jQuery.ready();
    }
}
 
// ready函数实现了最后一步,调用resolveWith,触发延迟对象的回调功能
//对于这个函数比较好奇的,可以看看holdReady函数的功能
ready: function( wait ) {
        if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
            return;
        }
        if ( !document.body ) {
            return setTimeout( jQuery.ready );
        }
         
        jQuery.isReady = true;
        if ( wait !== true && --jQuery.readyWait > 0 ) {
            return;
        }
        readyList.resolveWith( document, [ jQuery ] );
 
        if ( jQuery.fn.trigger ) {
            jQuery( document ).trigger("ready").off("ready");
        }
}

  

我们监听DOM加载,DOM加载完毕后进行回调,页面中散落各处的js脚本的执行时机是什么?

这个问题可以参考Html Dom加载 ,下面是我自己测试使用的页面,大家可以想想最终浏览器console打印的顺序是什么。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr" id="html">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Sizzle Test Suite</title>
    <script type="text/javascript" src="js/jquery-1.10.2.js"></script>
</head>
 
<body>
</body>
<script type="text/javascript" >
 
    window.onload = function (){
        console.log(1);
    }
     
    $(function(){
        console.log(2);
    });
        console.log(3);
 
    if ( document.addEventListener ) {
        document.addEventListener( "DOMContentLoaded", fn1, false );
        window.addEventListener( "load", fn2, false );
    }
      
    function fn1(){
        console.log(‘fn1‘);
    }  
    function fn2(){
        console.log(‘fn2‘);
    }          
     
    setTimeout(function(){
        console.log(‘in setTimeout‘);  
    },10000);
     
    setTimeout(function(){
        $(function(){
            console.log(‘in setTimeout jquery‘);       
        });
    },10000);
    </script>
</html>

jQuery源码学习(5)--$(fn)

上一篇:jquery水平滑动tab选项卡


下一篇:vue2.0报错:Syntax Error: TypeError: eslint.CLIEngine is not a constructor