(三)三段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( ... ) 代码段中所包含的代码。
方向之于生命