jQuery 源码分析笔记(2) 变量列表 |
本文标签:变量列表 _jQuery = window.jQuery; _$ = window.$; 这两个变量是jQuery唯一使用的两个全局变量 。在jQuery.noConflict()函数中,会把这两个变量恢复回去 。 对于浏览器检测,jQuery使用的是检查UserAgent,而没有使用特性检测 。 rwebkit = /(webkit)[ \/]([\w.]+)/, ropera = /(opear)(?:.*version)?[ \/](\w+)/, rmsie = /(msie) ([\w.]+)/, rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, 初始化函数init jQuery对JS对象的处理比较绕,而最终目的就是把jQuery选择器得到的结果变成和数组差不多的一个对象 。有length,first,last等 。因为$("...")就是从DOM树从选择一些节点出来 。但是,$还有很多其他功能,比如常用的$(function() { ... })用来页面加载后初始化执行,$("<..>...</...>")来直接得到一个节点,用来append到DOM树中 。 接下来从93行开始就是很长的一段init函数 。Init: function(selector, context, rootjQuery) 步骤: 1、Selector是非法参数:空字符,null和undefined则直接返回this 。即有默认属性的jQuery对象 。 2、Selector是DOMElement 。即用原生的JS,比如getElementById等得到的元素 。那么,相当于把原生的DOM对象用$包装一次 。把这个元素放到内部数组的第一个位置,并把length设置为1 。然后返回 。 3、特殊优化处理$("body") 。即document.body元素 。 4、Selector是以<开头,以>结尾的字符串 。那么假定是想用字符串新建一个DOM元素 。比如$("<a href=http://www.cnblogs.com">博客园</a>") 。为了安全起见,这里使用了一个正则表达式来检查,到底是<...>...</...>形式还是#id的形式 。 quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/ 。在quickExpr.exec(selector)后,如果是HTML字符串,那么会得到[match, match, undefined],而#id形式会得到[#id, undefined, id]的结果 。这样就把字符串区别开了 。 对于HTML字符串,如果只有一个tag,那么直接调用createElement 。否则调用一个createFragment辅助函数,这个函数使用createDocumentFragment,然后把所有tag都插进去 。 createFragment实现在5892行,这里有一个值得注意的地方就是jQuery对于HTML片段做了缓存处理 。而且对于不同的浏览器和元素有不同的处理,作者写了大段的注释说明 。归纳起来就是(1)只缓存小于0.5KB的小片段 。(2)selected状态不缓存 。(3)IE6的<object>和<embed>元素不缓存 。(4)WebKit不缓存元素的checked属性 。以上这些不缓存的原因是jQuery使用克隆(Clone)节点的方式进行缓存,而2-4提到的情况在Clone时会丢失 。jQuery使用了正则,或者jQuery.support辅助函数来进行是否缓存的策略判断 。这里先略过 。jQuery.support牵扯很多浏览器相关问题 。 5、如果在4中检查到是#id,则直接调用document.getElementById 6、如果selector是function,则把这个函数当作是document.ready的事件处理函数 7、剩余的各种情况,比如传入了context等 。统一调用一个find(selector)来处理 。这个函数以后再议 。(5109行,jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; 表明,其他复杂的selector表达式都扔给Sizzle项目了) jQuery基本成员 jQuery被设计成一个行为和数组很像的对象 。所以需要一些转换方法和基本属性 。 1、jquery:版本号 。最简单的得到版本号的方式:$().jquery 2、length和size():长度 。 3、toArray():转换成JS数组 4、get(num):返回第N个元素 。如果传入null,则直接返回toArray()的结果 。这里返回的就是DOMElement了 。 5、pushStack():参见http://api.jquery.com/pushStack/ 。内部new了一个新的jQuery对象,然后把elems和selector得到的结果合并进去,然后返回这个新的jQuery对象 。这里有个prevObject属性的设置,往下看end()函数 。 6、each(callback, args):遍历数组内的元素 。内部调用了$.each Utiltiy 。 7、ready(fn):其实和$(function() { })是等价的 。 8、eq(i):i允许正负数字,而且返回的仍然是jQuery对象,只不过只有一个元素了 。其实只是slice的包装 。 9、first()和last():其实就是eq(0)和eq(-1),很简单的一个包装 。 10、slice():根据参数获得数组一部分的引用 。内部使用pushStack实现的 。所以返回的也是一个新的jQuery对象 。 11、map(callback):对每个元素依次调用callback 。把原来的元素A的数组映射为元素B的数组 。callback就是元素A->元素B的映射函数 。函数式编程(FP)里很基础的一个概念 。 12、end(): 参见http://api.jquery.com/end 。这个是返回选择器的上一个状态 。返回的是jQuery.prevObject属性 。这个属性是在pushStack函数里面设置的,它在返回新的jQuery对象之前,把这个新对象的prevObject设置为this 。这样多次pushStack之后就变成了一个链表(chain) 。而end()就是沿着链表往前走一个节点 。经过了selector之后,根的prevObject是document 。比如$("body div").prevObject就是Document 。 extend函数 在jQuery基本成员之后,所有其他成员都是用extend加上去的 。声明: jQuery.extend = jQuery.fn.extend = function() { } 把target后面的所有object参数的属性全部赋值到target上,如果第一个参数是boolean值,则用来指定是否深拷贝 。然后返回修改过的target(不是新对象,extend函数直接修改原对象) 。 |