klvoek

klvoek

(三)三段new function的分析

现在我知道new function(){}能够干嘛了。接下来看一下代码中的三个new function(){ ... } 都做了神马?

1.第一个,判断浏览器型号和浏览器使用的CSS盒子模型是W3C盒子模型还是IE的Quirks模式

new function() {
    var b = navigator.userAgent.toLowerCase();
    // Figure out what browser is being used     jQuery.browser = {
        safari: /webkit/.test(b),
        opera: /opera/.test(b),
        msie: /msie/.test(b) && !/opera/.test(b),
        mozilla: /mozilla/.test(b) && !/compatible/.test(b)
    };
    // Check to see if the W3C box model is being used     jQuery.boxModel = !jQuery.browser.msie || document.compatMode == "CSS1Compat";
};

第一个好啊,他简单,就做了浏览器型号判断以及浏览器盒子模型的判断。

首先使用正则表达式判断navigator.userAgent.toLowerCase()字符串,以获取当前的浏览器型号。接下来是判断当前浏览器的W3C盒子模型,当然这都是因为ie有两种模式。

document.compatMode 这个是ie浏览器中存在的属性。

我们都知道,IE对盒模型的渲染在 Standards Mode和Quirks Mode是有很大差别的,在Standards Mode下对于盒模型的解释和其他的标准浏览器是一样,但在Quirks Mode模式下则有很大差别,而在不声明Doctype的情况下,IE默认又是Quirks Mode。所以为兼容性考虑,我们可能需要获取当前的文档渲染方式。

document.compatMode正好派上用场,它有两种可能的返回值:BackCompat和CSS1Compat,对其解释如下:

BackCompat Standards-compliant mode is not switched on. (Quirks Mode)

CSS1Compat Standards-compliant mode is switched on. (Standards Mode)

在实际的项目中,我们还需要在获取浏览是否IE,这样就可以通过判断document.compatMode的值得到IE的渲染模式了。

 

第二个:jQuery.ready的监听与响应

new function(){
    var e = ("blur,focus,load,resize,scroll,unload,click,dblclick," +
        "mousedown,mouseup,mousemove,mouseover,mouseout,change,reset,select," +
        "submit,keydown,keypress,keyup,error").split(",");
    // Go through all the event names, but make sure that     // it is enclosed properly     for ( var i = 0; i < e.length; i++ ) new function(){
             
        var o = e[i];
         
        // Handle event binding         jQuery.fn[o] = function(f){
            return f ? this.bind(o, f) : this.trigger(o);
        };
         
        // Handle event unbinding         jQuery.fn["un"+o] = function(f){ return this.unbind(o, f); };
         
        // Finally, handle events that only fire once         jQuery.fn["one"+o] = function(f){
            // Attach the event listener             return this.each(function(){
                var count = 0;
                // Add the event                 jQuery.event.add( this, o, function(e){
                    // If this function has already been executed, stop                     if ( count++ ) return;
                 
                    // And execute the bound function                     return f.apply(this, [e]);
                });
            });
        };
             
    };
     
    // If Mozilla is used     if ( jQuery.browser.mozilla || jQuery.browser.opera ) {
        // Use the handy event callback         document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
     
    // If IE is used, use the excellent hack by Matthias Miller     // http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited     } else if ( jQuery.browser.msie ) {
     
        // Only works if you document.write() it         document.write("<scr" + "ipt id=__ie_init defer=true " +
            "src=//:><\/script>");
     
        // Use the defer script hack         var script = document.getElementById("__ie_init");
        script.onreadystatechange = function() {
            if ( this.readyState == "complete" )
                jQuery.ready();
        };
     
        // Clear from memory         script = null;
     
    // If Safari  is used     } else if ( jQuery.browser.safari ) {
        // Continually check to see if the document.readyState is valid         jQuery.safariTimer = setInterval(function(){
            // loaded and complete are both valid states             if ( document.readyState == "loaded" ||
                document.readyState == "complete" ) {
     
                // If either one are found, remove the timer                 clearInterval( jQuery.safariTimer );
                jQuery.safariTimer = null;
     
                // and execute any waiting functions                 jQuery.ready();
            }
        }, 10);
    }
    // A fallback to window.onload, that will always work     jQuery.event.add( window, "load", jQuery.ready );
     
};

第二个属于很大的代码断了,前半部分大体明白是在jQuery对象上绑定常见事件,但是由于不了解bind、event的实现方式所以这部分代码具体实现逻辑不是很明白,所以能放下就暂且放一放。后半部分代码则是对jQuery.ready方法的处理,在何时页面文档加载完成可以执行jQuery.ready方法了。这一段比较容易看懂(注释很多),主要是跨浏览器的兼容。

Mozilla 浏览器算是比较简单,safari虽然代码多一点,但是实现逻辑也容易懂-就是不停的检查document的readyState,如果是loaded或 complete 则可以触发jQuery.ready了。而ie则用到了一个excellent hack。最后的一段代码 jQuery.event.add(window, "load",jQuery.ready);是一般能工作的模式。所以这里猜测jQuery.ready 应该也是run once(运行一次)的吧。

 

第三个:主要是jQuery对象上的Ajax事件定义?

// Attach a bunch of functions for handling common AJAX events new function(){
    var e = "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess".split(',');
     
    for ( var i = 0; i < e.length; i++ ) new function(){
        var o = e[i];
        jQuery.fn[o] = function(f){
            return this.bind(o, f);
        };
    };
};

这一个代码与第二个的前半部分代码相似。实现的功能不是很理解,等后面读一些代码后再进一步理解。但是jQuery.fn[o] = function(){}的用法应该能看懂。注意是字幕o而不是数字0。

在这个代码之前还有一段IE兼容的代码,为的是在IE下创建XMLHttpRequest Ajax请求对象:

// If IE is used, create a wrapper for the XMLHttpRequest object if ( jQuery.browser.msie )
    XMLHttpRequest = function(){
        return new ActiveXObject(
            navigator.userAgent.indexOf("MSIE 5") >= 0 ?
            "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP"
        );
    };

IE浏览器可是有自己的XMLHttpRequest 创建模式的,经常接触Ajax的应该对此不陌生的。

总结:

到此为止,我们脑海里应该清晰了jQuery部分代码,并且对jQuery中用到的部分js特性有了了解。浏览器版本判断、CSS盒子模型的判断(这个在jQuery里起到的什么作用呢?)、页面加载完成的兼容代码、XMLHttpRequest兼容代码、extend的实现、jQuery.method = jQuery.fn.method = function(){ ... }的使用方式。接下来,需要更深层次的去理解和分析jQuery.extend( ... ) 代码段中所包含的代码。

标签: jQuery, extend, ajax, prototype
Posted by klvoek @ 2012-2-12 14:47:10 阅读(109) 评论(0)
上一篇:(二)解决前6条
下一篇:(四)第一个jQuery.extend代码段

我也来参与讨论

你还可以输入600/600个字符 发表评论
称呼: (必填) 登录 | 开通博客
邮箱: (选填) 你的邮箱地址不会被公开
网站: (选填)
验证码: (必填)
看不清换一张 看不清楚换一张