剖析jQuery源码

来源:互联网 发布:钉钉mac 编辑:程序博客网 时间:2024/06/03 12:41

@description analyzing jquery.1.3.1.js
@author yanquan.xu(Henry)
@date 2013/5/11 19:19
@place campus

由于深爱着javascript语言,而对于业界的框架的层出不穷,我依然选择了jquery。并非因为其它框架不好,而是
自然而然的选择和机缘的认识,所以一直用到现在,之后也会说它的不好。^.^,因为没有完美的东西。
使用那么长得时间,直到前几天才翻开它的源码看了一下,感触有一点,怕自己忘记,所以整理了一下,如果不好,
记得告诉我。^.^
我下载了jquery.1.3.1的版本进行阅读,因为所有版本的核心思想都是一样的,后期更新到现在的1.9和即将出来的2.0
的核心都是一样的,只是由于感觉新版本的功能增加得太多,代码过于偏大不便阅读,所以百度到了1.3版本的。
开始打开的源码通常都有一些废话在前面,就像下面一样:
/*!
* jQuery JavaScript Library v1.3.2
* http://jquery.com/
* Download by http://www.codefans.net
* Copyright (c) 2009 John Resig
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*
* Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
* Revision: 6246
*/
其实不是废话啦,这是每个公司或者个人的著作信息。这个不说了。
然后代码就以这个开始了:(function(){
当你把内部全部代码删除掉,其实完整的写法应该是:(function(){})();这个就是特别常见的闭包了,其实我第一次
听到闭包还是会觉得生疏的,它的叫法意义类似于命名空间或者一个类一样,这样更亲切。之所以在这里面写那么多代码,
就是不让里面的世界影响到了外面的世界,因为你的总世界是一个web页面,而不能因为你写的代码影响到别人的代码,变量
重写了别人的,就是占着别人的位置啦。
然后声明了很多个变量,抽取了一些如下:
var 
// Will speed up references to window, and allows munging its name.
window = this,
// Will speed up references to undefined, and allows munging its name.
undefined,
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$,

jQuery = window.jQuery = window.$ = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context );
},
为什么这么声明,因为js很随和,一样可以分开写,也可以不强制写var(你可以把var删掉都没关系,js很友好。)
其中觉得预先准备是做得很好的,比如将当前的执行环境对象即环境变量window存储到内部变量window里面,环境变量就是
this。this指向了window,因为闭包的调用是window调用的,所以谁用了这个闭包,this就指着它。下面有个undefined,这
也许让我们费解,其实只是基本功的问题,因为没有人会认为undefined可以当做变量,只曾经模糊的记住undefined好像是
关键字,和null一样类似,或者没有搞清楚null和undefined区别。这里没有代表很多意思,只是说明了变量undefined的值是
undefined,好像很弱智很罗嗦啊。。。其实这是为了别人重写了undefined变量。第三变量的声明把环境中得jQuery变量暂时
存储到_jQuery变量,相当于打入冷宫,存在着闭包中,至于何时它能重见天日,就看你那时候用noConflict()函数把它解放
出来。同样的道理,$是jQuery的姐妹一样,形影不离,自然而然也要进入冷宫。之所以有如此做法,是下面的代码需要这个
位置,所以不得不解决一下冲突。然后就是有点用的代码的开始了,整个框架叫jQuery的声明由此开始,它就是个函数,
参数是选择符号和上下文,里面的实现便是返回一个jQuery里面的fn的init类的对象。
接下来就是一些累赘的正则表达式,如果有兴趣可以看看它的正则的功力。如下:
// (both of which we optimize for)
quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
// Is it a simple selector
isSimple = /^.[^:#\[\.,]*$/;
其实就是匹配选择器的正则。
然后开始进入正文了,重心的代码开始于:
jQuery.fn = jQuery.prototype = {
此句马上进行了框架的初始化函数和原型的定义,比如css修饰函数,attr属性函数,init初始化函数,其实init函数
也是大家所说的选择器函数,被公认为写得最好的,我却不这么认为,因为我看完了所有代码后,发现它只是思路清晰分类
的体现,只是冰山一角的体现。还有很多函数,比较多,就不累赘了,它们都是jQuery对象的函数,作用于对象上面,这个
非常重要。只是大家会觉得很奇怪,为什么原型的方法会作用于原型的内部类的对象。慢慢看完原型的实现后,我们又看到
了这一句:jQuery.fn.init.prototype = jQuery.fn;我至始至终觉得就是这一句就是这个框架的亮点,它让我豁然开朗和
晴天霹雳的感觉,它把初始化函数们又回挂到了初始化函数内部类的原型,很绕口,没办法,重点就是这里。我简写一下,
或许更便于理解:
jQuery.fn = jQuery.prototype = {
init:function(){}
};
jQuery.fn.init.prototype = jQuery.fn;
至此已经很简便了,只能意会,如果看不懂,我也没办法。它的优点在于扩大了原生js操作dom元素的能力,你可以看到
选择器函数init里面有一句:var elem = document.getElementById( match[3] );然后返回了这个元素。当我们可以用扩展的
原型函数的时候,就会发现css(key,value)比你写elem.style.key = value;要好用得多。
往下看,又会看到非常核心的函数出场了,就是集成函数的实现:
jQuery.extend = jQuery.fn.extend = function() {
很明显,它又挂到原型函数里面去了,但是也留给了jQuery对象里面了,如果说成是jQuery类的静态方法,你可能更能
理解,是的,之后会看到它的强大作用。它的实现不亚于选择器函数,实现了深层集成和浅层的集成,实现不累赘讲述,因为
每一个重要的函数代码,jQuery都写到一起,很长,不喜欢这样的风格。不过反正也没人看,无所谓。
然后我们在extend下面可以看见,因为作者又集成了很多函数,太长了,不说明了,只是应该注意的是,这些函数不仅仅
集成到了jQuery.fn里面,而且jQuery里面也会有得。就是说对象方法当然有,但是也是jQuery静态方法,因为下面代码实现
会用到这些函数。
接下来就是浏览器的判断,就是正则表达式的测试:
jQuery.browser = {。。。
接下来我们可以看到作者将函数进行了细化扩展,比如我们的所有节点查找的函数都是经过刚集成的函数得以实现的。并且
在fn里面扩展了这些细化,使得我们可以随心所欲的查找到我们需要的节点,比如siblings(),next(),prevAll(),children()等等
然后又用each函数扩展了许许多多的函数,不一一列举了,好烦啊。总之有两种扩展啦,就是它了each和extend,但是扩展
的对象是又区别的。然后它罗嗦的写了那么多函数之后,引用了点别人的东西,这个东西可大了:
/*!
* Sizzle CSS Selector Engine - v0.9.3
* Copyright 2009, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
*/
这个就很厉害了,就是著名的Sizzle,这个是css选择器的引擎,它是强大的选择器的实现。jQuery依靠它,完成了其余工作
的实现。总之,又是一阵罗嗦之后,我们翻到了下面,惊讶的发现它又是集成又是集成又是集成,然后代码就这么集成完了,
至此,你终于知道这个extend是多么强大和重要。
说千道万,不如自己去看一下。不过感觉jQuery包装是很好的,让我们觉得很精美,但是里面却是“无比丑陋”,因为它
的目标只有一个,就是写得少,实现多。正因这个原因,所以让它的代码是非常浓缩的精华写法,不按照平常我们的语法类似,
而是怎么高效,怎么简洁,怎么方便怎么写。反正我们都只用它,不会看它的。虽然是如此,不会影响它在我心中的地位。
里面的实现实在很有欣赏的妙处,比如扩展的写法,浏览器ie的return id的bug,高效快速的引用,正则表达式的高效
利用。

-----------------------------------------------------------------------------------------JavaScript群:55732875

原创粉丝点击