jQuery源码分析版权所有Jquery源码分析1、概述jQuery是一个非常优秀的JS库,与Prototype,YUI,Mootools等众多的Js类库相比,它剑走偏锋,从web开发的实用角度出发,抛除了其它Lib中一些中看但不实用的东西,为开发者提供了优美短小而精悍的类库。其使用简单,文档丰富,而且性能高效,能极大地提高web系统的开发效率。因此可以说是web应用开发中昀佳的Js辅助类库之一。大部分开发者正在抛弃Prototype,而选择Jquery做为他们进行web开发的JS库。如是开发人员仅仅只知道文档中的简单的使用方法,却不明白Jquery的运行原理和内部机制,在使用jquery时,肯定会碰到许多的问题。这些问题有一部分是Jquery的Bug。大部分是自身的使用不当而造成的。而文档的简单的使用说明很难解决问题。在调试基于jQuery的web应用时,很多时候都要跟踪进入jQuery对象分析其运行状态以了解出错的原因。如果对于web的应用的页面运行性能和效率有所要求的话,那么我们更应该去明白其运行机理和核心源码。但是jQuery源码不像其它的类库那样,它有点晦涩,难懂。这就是本源码分析的原因,让所有使用jQuery的读者,能快速上手jQuery的源码,并在开发中得心应用。Jquery的网络资源丰富,但Baidu了很久,很难找到那种完全深入地分析Jquery源码的文稿。倒是Jquery的开发者,JohnResi的《ProJavascriptTechniques》涉及到Jquery的源码的分析,但是其主指还是在于JavaScript的使用。那本书并不能使我们完全细致地了解Jquery的源码。作者:prk(彭仁夔)QQ:546711211Email:sjkjs155@126.comBlog:(查询)2、构建jQuery对象在本节中,我们会就Jquery的运行机制和设计理念进行分析及说明。本节主要从jQuery的设计理念e及其构建的源码进行剖析。2.1、jQuery的设计理念在使用jQuery之前,我们也许会问jQuery是什么?其实它的名字就很能反映其主旨的。J是的JS,Query是指查询。如果把jQuery看作是一个查询的JS类库。它和prototype,mootools等类库一样,为Web的Js开发提供辅助功能。那为什么要选用jQuery呢?在jQuery出现之前,Prototype,YUI都已经是成熟的Js的框架,而且是各有各的特点。并且市场的书和使用文档都很详尽。为什么开发员会抛弃它们,而使用后起之秀的jQuery,它有什么优秀的特性吸引开发人员呢?回答这个问题,我们得明白jQuery的设计理念。回忆或想象一下,我们在web开发中是如何使用JS?绝大多数时间都是进行如下五个方面的事情:1、采用getElementById在Dom文档中找到Dom元素,然后取值或设值。2、对元素采用innerHTML取其内容或设定其内容。3、对元素进行事件的监听(如click)。4、通过改变元素的CSS样式如height,达到视觉上的效果。5、通过Ajax从服务器取值,往指定元素里添充内容。从上面可以看,在使用Js开发时候就是在对Dom元素在进行操作。这个Dom元素可能是单个或是集合的形式。对元素元素操作,对于document,window是可以直接引用,但是对于其它的Dom元素,我们得从Dom文档树查找得到吧。这样的话就可以把JS的操作分析两部分任务,一、查找Dom元素,二、对Dom元素进行操作。对于使用JS熟练的开发者而言,也许手写document.getElementById或elment.getElementsByTagName这样冗长的直接查找Dom元素觉得不是什么问作者:prk(彭仁夔)QQ:546711211Email:sjkjs155@126.comBlog:源码分析版权所有题,许会对element的event,attribute,style等操作也不含糊,但是对于IE、mozilla等几大主流的浏览器的兼容足够让每一个JS高手头疼。这是使用JS类库的主要原因。JS类库只要用得恰当的话,也不一定比直接采用JavaScript的原始函数和对象的运行效率低。但是其却能极大地提高开发的效率。自从Prototype采用$符号做为document.getElementById的缩写,$符号似乎成了查找元素的代理符号。但是这种简单的查找并不能满足web应用的需要。很多时间我们需要像CSSselector那样查找Dom元素。jQuery从这里出发,采用$符号做为查找元素的代理。它不再是那种简单的getElementById,而是功能强大的CSSselector的选择器。这也就是query的本意。解决了查找的元素的任务,之后就是对元素的操作。jQuery抛弃了prototype中那么对Array,Object,Function,Event等JS原生对象的扩展。把所有的心思都放在解决实际问题的Dom元素的操作上。它不仅简化Dom元素原生的冗长名字的函数名和众多难记的方法,而且在简化这些方法的同时提供了更为便捷且兼容浏览器的功能。同时那些实用的功能一个都没少,如Ajax,Event,Fx,CSS的操作应有仅有。Prototype中Event,Ajax等众多的对象不但让人觉得烦琐难记,而且让人感觉有点畏惧感。jQuery在设计时就考虑到这一点。它提供了统一的入口,就是一个对象:jQuery对象($)。所有的操作,变化都是针对这个对象。现在可能给jQuery一个明确的解释:jQuery实质就是一个查询器。在查询器的基础还提供对查找到的元素进行操作的功能。这样说来jQuery就是查询和操作的统一。查询是入口,操作是结果。jQuery对象在代码分成两大部分,一部分是jQuery的静态方法,也可以称作实用方法或工具方法,通过jQuery.xxx()的jQuery命名空间直接引用。第二部分是jQuery的实例方法,通过jQuery(xx)或$(xx)来生成jQuery实例,然后通过这个实例来引用的方法。这部分的方法大多数是从采用静态方法代理来完成功能。真正的功能性的操作都在jQuery的静态方法中实现。这些功能细分起来,可以分成以下几个部分:1、Selector查找元素。这个查找不但包含基于CSS1~CSS3的CSSSelector功能,还包含其对直接引用或间接引用Dom元素而扩展的一些功能。2、Dom元素的属性操作。Dom元素可以看作html的标签,对于属性的操作就是对于标签的属性进行操作。这个属性操作包含增加,修改,删除,取值等。3、Dom元素的CSS操作。CSS是控制页面的显示的效果。对CSS的操作作者:prk(彭仁夔)QQ:546711211Email:sjkjs155@126.comBlog:源码分析版权所有那就得包含高度,宽度,display等这些常用的CSS的功能。4、Ajax的操作。Ajax的功能就是异步从服务器取数据然后进行相关操作。5、Event的操作。对Event的兼容做了统一的处理。6、动画(Fx)的操作。可以看作是CSS样式上的扩展。2.2、jQuery对象的构建上一节分析了从整体上分析了jQuery的原理,从其原理可以看出,其统一的入口就是jQuery对象。那么这个对象是如何生成的呢?上一节还提到了jQuery的实质是Query,那么生成jQuery对象就可能看作是构建并运行一个查询器。既然是查询,肯定会有查找到的结果(Dom元素),那么这些结果又存放在哪里呢?昀好的地方当然是jQuery对象内面。查询的结果可能是单个元素,也可能是集合如NodeSet。也就是说jQuery对象内面应该有一个集合。且这个集合是用来存放查询到Dom元素。但jQuery对象是所有操作的统一入口,那么它的构建就不应只局限于从Dom文档树中查询到Dom元素,有可能是从别的集合中转移过来的Dom元素,或是html的片断生成的Dom元素。Jquery文档中提供了四种构建方式:jQuery(expression,[context]),jQuery(html),jQuery(elements),jQuery(callback)。其中jQuery可以用$代替。这四种方式是经常用到。其实Jquery的参数可以是任何的元素。也就是说任何的参数都可以构建jquery对象。举几个例子:1、$($(“P”))可以看出其参数可以是jQuery对象或ArrayLike的集合。2、$()是$(document)的简写。3、$(3)会把3放到jQuery对象中集合中。对于如$(3)这样的其中元素(如ArrayLike集合的元素)不是Dom元素,昀好不要构建jQuery对象,jQuery对象的方法设计的目的都是针对于dom对象的而进行的操作。如果不清楚其使用的话,很有可能会导致错误。上面讲了这么多大道理,现在从源码的角度细细分析:通过jQuery(xxx)的调用实现没有生成对象,它的this是指向window对象的。那么jQuery的那些实例方法是怎样继承过来的呢?看一下:varjQuery=window.jQuery=window.$=function(selector,context){returnnewjQuery.fn.init(selector,context);①};作者:prk(彭仁夔)QQ:546711211Email:sjkjs155@126.comBlog:的总入口,jQuery对象不是通过newjQuery来继承其prototype中的方法,而是jQuery.fn.init函数生成的对象。这里我们可以看出对于jQuery.prototype添加一些函数集的对象的意义不大。newjQuery()还是可以的,但是生成的jQuery对象在return时会被抛弃。故不要用newjQuery()来构建jQuery对象。jQuery对象其实就是jQuery.fn.init对象。那么jQuery.fn.init.prototype上就是挂着jQuery对象的操作方法。如jQuery.fn.init.prototype=jQuery.fn;有时间可能会担心在589行就实现了把jQuery.fn中的函数放到jQuery.fn.init.prototype上去,那么之后的通过jquery.fn.extend的方法怎么办呢?这里是对jQuery.fn的引用。在扩展jQuery的时候,只要把相关的函数extend到jQuery.fn就可以了。现在我们看一下jQuery.fn.init是怎么完成工作的:init:function(selector,context){selector=selector||document;//确定selector存在//第一种情况Handle$(DOMElement)单个Dom元素,忽略上下文if(selector.nodeType){②this[0]=selector;this.length=1;returnthis;}if(typeofselector==string){//selector为string③varmatch=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])//第二种情况处理$(html)-$(array)④selector=jQuery.clean([match[1]],context);else{//第三种情况:HANDLE:$(#id)//处理$(#id)varelem=document.getElement