认识第一个比较重要的方法jQuery.fn.init
源码如下:
selector = selector || document; if ( selector.nodeType ) { this[0] = selector; this.length = 1; return this; }
selector = selector || document 暗示了如果$(),那么就相当于$(document)
selector.nodeType用来判断是否是一个domElement对象,如果是直接将本对象包装成jquery对象返回,这里要说明一点,实际jquery对象是一个伪数组或者说是一个功能异常强大的集合,你可以通过下标去访问里面的元素和length属性,但它不会像数组一样去帮你维护里面的元素,比如你将length设为空,它不会帮你将里面的元素清空,因为他是一个伪造的。
if ( typeof selector == "string" ) { .... }else if ( jQuery.isFunction( selector ) ) return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); return this.setArray(jQuery.makeArray(selector));
判断是否是字符串,情况比较多,稍后讨论,先看简单的,好像也不太简单
jQuery.isFunction( selector ) 判断传进来的是否是一个函数
isFunction函数体如下:
return !!fn && typeof fn != "string" && !fn.nodeName && fn.constructor != Array && /^[\s[]?function/.test( fn + "" );
!!fn强制返回boolean型,然后否定了它不是字符串,不是dom元素,不是数组,然后用一个正则进行验证,为什么要加个"^[\s[]?"让我很困惑,因为这是一个全局函数所以才判断这么多,实际上就这个逻辑关系,只用最后一个验证就行了,因为前面已经都有对应的判断了,不过这个方法还是相当具有价值的,多多品味
jQuery( document )返回是一个骨子里是document的jquery对象
[ jQuery.fn.ready ? "ready" : "load" ]如果jQuery.fn存在ready属性,返回[ready]否则返回[load],这种写法很值得借鉴,简洁高效
下面找寻load,ready方法
load : (约2420) 牵涉事件,暂时搁置一下
ready : (约2282)
jQuery.fn.ready: function(fn) { bindReady(); //关于事件暂时不讨论 if (jQuery.isReady) fn.call(document, jQuery); else jQuery.readyList.push(function() { return fn.call(this, jQuery); }); return this; }jquery有一套快速的检查文档是否加载完毕的例子,这个要比传统的window.onload要快,他的实现是通过一个计时器,不停的检查,知道加载好后将jQuery.isReady属性等于true
,所以上面这段代码意思就是,如果没有加载好就将其放入readyList数组中,当前的this指向调用ready的jquery对象(即$(document)),而且这个函数还被注入了jQuery参数,所以想查看readyList里面的个数 $(function(j){alert(j.readyList.length)}),如果dom已经加载好,就会直接执行
当dom从未加载好到加载好后,会调用全局的jQuery.ready(约2304),将isReady改为true,然后遍历readyList数组,执行里面的方法,一定要把最后页面执行$()里面function这个过程想通
下一个return this.setArray(jQuery.makeArray(selector));
setArray: function(elems) { this.length = 0; Array.prototype.push.apply(this, elems); return this; }因为是伪数组,所以记住在改变数组时要自己维护length,剩下就不解释了,属于借鸡生蛋的做法
makeArray: function(array) { var ret = []; if (array != null) { var i = array.length; if (i == null || array.split || array.setInterval || array.call) ret[0] = array; else while (i) ret[--i] = array[i]; } return ret; }注意有length属性不仅仅是array,还有arguments,function,伪数组(例如jquery对象),window。i == null主要是针对没有length属性的,比如object,12,true这样的基本类型,这函数的意义就是无论什么将它构造成一个数组。作者之所以分成两个方法,是考虑到粒度的问题,这种粒度对后面的重用会大有帮组
最麻烦的:if ( typeof selector == "string" )这块
首先来看看我们已经分析了那些还剩下那些情况:
1.if ( selector.nodeType ) 处理了dom对象
2.if (jQuery.isFunction(selector)) 处理预加载函数这一块
3.this.setArray(jQuery.makeArray(selector)) 处理了数组和伪数组情况
api中提供的方法,属于字符串的一块
1) 处理选择器,如 #id,.class,:input 之类的
2) 直接构建dom,$("<div><p>Hello</p></div>")
init方法上有两个参数selector, context其中context就是规定它的寻找范围,主要是处于性能上的考虑,假设已经了解dom的结构,可以加快锁定元素的速度,默认为document
var match = quickExpr.exec(selector); if (match && (match[1] || !context)) { if (match[1]) selector = jQuery.clean([match[1]], context); else { var elem = document.getElementById(match[3]); if (elem) { if (elem.id != match[3]) return jQuery().find(selector); return jQuery(elem); } selector = []; } } else return jQuery(context).find(selector);
quickExpr : "/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/"只关注两种情况,一种是直接针对构建dom的,一种是针对id选择器的,特别对id照顾是因为getElementById的速度是最快的,之所以会多出if (elem.id != match[3])这种情况是因为我们的ie老大哥在解析input这类的标签时在没有id有name的时候,会将name取代id,对于这种擅作主张的行为很不能接受,所要小心了。
jQuery.clean([match[1]], context) : 方法实现是创建一个临时的div,然后将
<(.|\s)+>添加到这个div的innerHTML上,会自动生成dom对象,然后解析这个对象,打包成数组返回。后面会详细说明
如果没有匹配结果或存在context的情况下,将执行jQuery(context).find(selector)方法通过选择器来寻找结果,这个选择器一块的知识后面会提到
1 楼
harry_2013
2010-11-26
内容没看,不过这个标题很吸引人哦。不知道算不算标题党