当前位置:编程学习 > JAVA >>

jQuery:理解$(document).ready()的特殊写法

看书时注意到下面两条语句的功效是相同的,
$(function(){alert("hello!");});  
$(document).ready(function(){alert("hello!");}); 
这个特殊写法就是用$()代替$(document).ready(),类似于(有差异)window.onload弹出个窗口:
查看jQuery1.8.3源代码,是这样封装的:
(function( window, undefined ) {  
    /*...jQuery源代码全部都在这里了...*/ 
})( window );  
下列语句把封装在内部的jQuery先赋给window.$,紧接着再赋给window.jQuery。这意味着在实际使用时window.$和window.jQuery是一回事。因为$这个符号只有1个字母,比jQuery短,所以更常用一些,但要注意到$非jQuery所独有,节约字母的代价是增加了命名冲突的风险。
// Expose jQuery to the global object  
window.jQuery = window.$ = jQuery; 
 
下面是jQuery的初始化语句(注意到此时函数并未执行):
// Define a local copy of 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的定义,这是一个对象,其中有一个叫init的函数元素: 
jQuery.fn = jQuery.prototype = {  
    constructor: jQuery,  
    init: function( selector, context, rootjQuery ) {  
        var match, elem, ret, doc;  
 
        // Handle $(""), $(null), $(undefined), $(false)  
        if ( !selector ) {  
            return this;  
        }  
 
        // Handle $(DOMElement)  
        if ( selector.nodeType ) {  
            this.context = this[0] = selector;  
            this.length = 1;  
            return this;  
        }  
/*...以下省略...*/ 
继续下去,init中有一段逻辑:
// HANDLE: $(function)  
// Shortcut for document ready  
} else if ( jQuery.isFunction( selector ) ) {  
    return rootjQuery.ready( selector );  
晕了晕了,rootjQuery的定义又回到了jQuery:
// All jQuery objects should point back to these  
rootjQuery = jQuery(document); 
有点递归的意思了,嗯,就是递归。jQuery不仅仅是一个函数,而且还是一个递归函数。
如果调用jQuery时输入的是一个函数,例如文章开头提到的:
$(function(){alert("hello!");}); 
那么这个函数就会走到rootjQuery那里,再回到jQuery,执行jQuery(document).ready。而$与jQuery是一回事,这样就解释了$(inputFunction)可以代替$(document).ready(inputFunction)。
现在还不想结束此文,我的问题是$(document)做了什么?嗯,还是要进入到jQuery.fn.init,确认存在nodeType属性,达到“Handle $(DOMElement)”的目的。怎么Handle呢?具体就是把输入参数(此时为document)赋值给this的context属性,然后再返回this。也就是说,$(document)执行完了返回的还是jQuery,但是情况发生了变化,具体就是context属性指向了输入参数(此时为document)。暂时还不明白绕这么大个圈子为context(上下文)属性赋值有何意义?
接下去的问题可能会是$(document).ready和window.onload的区别?提取ready函数的定义如下:
ready: function( fn ) {  
    // Add the callback  
    jQuery.ready.promise().done( fn );  
 
    return this;  
}, 
阅读代码探究promise是有点晕啊,想到自己的iJs工具包了,打印jQuery.ready.promise()如下:
    [Object] jQuery.ready.promise()
        |--[function] always
        |--[function] done
        |--[function] fail
        |--[function] pipe
        |--[function] progress
        |--[function] promise
        |--[function] state
        |--[function] then
进一步打印整理done函数代码如下(这下彻底晕了~~):
function() {   
    if ( list ) {   
        // First, we save the current length   
        var start = list.length;   
        (function add( args ) {   
            jQuery.each( args, function( _, arg ) {   
                var type = jQuery.type( arg );   
                if ( type === "function" ) {   
                    if ( !options.unique || !self.has( arg ) ) { list.push( arg ); }   
                } else if ( arg && arg.length && type !== "string" ) {   
                    // Inspect recursively add( arg );   
                }   
            });   
        })( arguments );   
        // Do we need to add the callbacks to the   
        // current firing batch?   
        if ( firing ) {   
            firingLength = list.length;   
            // With memory, if we're not firing then   
            // we should call right away   
        } else if ( memory ) {   
            firingStart = start; 
       fire( memory );   
        }   
    }   
    return this;   
好在代码不长,看起来关键就在于fire函数了。嗯,找回一丝清醒了。在上面的done函数里面可以注意到使用了默认的arguments变量,将注入的函数push到了list数组。下面是fire函数:
fire = function( data ) {  
    memory = options.memory && data;  
    fired = true;  
    firingIndex = firingStart || 0;  
    firingStart = 0;  
    firingLength = list.length;  
    firing = true;  
    for ( ; list && firingIndex < firingLength; firingIndex++ ) {  
        if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {  
            memory = false; // To prevent further calls using add  
            bre
补充:web前端 , JavaScript ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,