jQuery源码学习笔记一

 

不知该起什么题目,随便吧。不过我没心情逐一介绍其API,那是文档的事。比起那些随时会被废弃的方法,我更着重其内在的技术,所以我选择读源码。由于我从不用jQuery,可能理解有些偏差。不过,看了这么多类库,有许多东西都是共通。比如这个jQuery对象就是DOM对象的加工工场,把DOM对象包裹其中,外围是许多便捷的方法。我们可以想象一下太阳系,DOM就是太阳,css就其中一个行星,attr是另一个……之所以选择类数组形式,是为了用map,filter等发端于数组的同名方法进行大数量的DOM操作。好了,下面就直接写在注解中吧。

01. //@author  司徒正美|なさみ|cheng http://www.cnblogs.com/rubylouvre/ ; All rights reserved
02.       var 
03.       window = this,
04.       undefined,
05.       _jQuery = window.jQuery,
06.       _$ = window.$,
07.       //把window存入闭包中的同名变量,undefined的情形一样,的确是让更内围的作用域的方法调用时,不要跑到那么远
08.       
09.       //_jQuery与_$用于以后重写
10.       jQuery = window.jQuery = window.$ = function( selector, context ) {
11.         //用于返回一个jQuery对象
12.         return new jQuery.fn.init( selector, context );
13.       },
14.       //这东西看起来很唬人,其实就是想获取元素的标签名或ID
15.       quickExpr = /^[^<]*(<(.|/s)+>)[^>]*$|^#([/w-]+)$/,
16.       //检测是否一个简单的选择器,怎样才为之简单呢?
17.       //就是一重类选择器,也就是这个样子.red,如果.red .dd就不合要求了
18.       //看它的限制,一定要是类选择器,后面不能跟伪类选择器,ID选择器,属性选择器,第二重第三重的类选择器
19.       //与并联选择器
20.       isSimple = /^.[^:#/[/.,]*$/;
01. jQuery.fn = jQuery.prototype = {
02.    init: function( selector, context ) {
03.      //如果为空就把document塞进jQuery对象中
04.      selector = selector || document;
05.      //如果第一个参数是DOM对象,那它肯定有nodeType吧,
06.      //是就开始创建索引,创建类数组对象
07.      //说白了就是一个hash,只不过键是数字,值是DOM对象
08.      //不过它除了[0],[1]等数字键外,还有"css","attr","addClass"等字符串键,它们的值对应方法
09.      //length属性是就Array.prototype.slice与map,filter等方法准备
10.      //this.context是作为下次搜索的起点,如DOMElement.getElementsByTagName("span")
11.      if ( selector.nodeType ) {
12.        this[0] = selector;
13.        this.length = 1;
14.        this.context = selector;
15.        return this;
16.      }
17.      //如果传入的是CSS selector字段
18.      if ( typeof selector === "string" ) {
19.        //如果是很单的tagName或ID
20.        var match = quickExpr.exec( selector );
21.        //选择器类似h1的情形        
22.        if ( match && (match[1] || !context) ) {
23.          //如果是标签
24.          if ( match[1] )
25.          //clean方法不厚道地放到800行之后,针对许多特殊情况做处理
26.            selector = jQuery.clean( [ match[1] ], context );
27.          // HANDLE: $("#id")
28.          else {    
29.            var elem = document.getElementById( match[3] );
30.            // Handle the case where IE and Opera return items
31.            // by name instead of ID
32.            //在IE与Opera中,ID并不一定返回一个元素,这时用name来查找
33.            if ( elem && elem.id != match[3] )
34.              return jQuery().find( selector );
35.            //由于ID有排他性,因此需要清空前面的context,        
36.            var ret = jQuery( elem || [] );
37.            //重设搜索起点,
38.            ret.context = document;
39.            //安装DOM对象
40.            ret.selector = selector;
41.            return ret;
42.          }
43.          // HANDLE: $(expr, [context])
44.          // (which is just equivalent to: $(content).find(expr)
45.        } else
46.        //处理非常复杂的选择器,如镶嵌的CSS3选择器
47.          return jQuery( context ).find( selector );
48.        // HANDLE: $(function)
49.        // Shortcut for document ready
50.        //著名的DOMReady的,就是美元符号里面传入一个匿名函数
51.      } else if ( jQuery.isFunction( selector ) )
52.        return jQuery( document ).ready( selector );
53.      // Make sure that old selector state is passed along
54.      if ( selector.selector && selector.context ) {
55.        this.selector = selector.selector;
56.        this.context = selector.context;
57.      }
58.      //确保以jQuery的类数组对象返回
59.      return this.setArray(jQuery.isArray( selector ) ?
60.        selector :
61.        jQuery.makeArray(selector));
62.    },

基本上init就是个大熔炉,根据传入参数的类型做出不同的处理,如DOM对象,字符串,数组对象与NodeList这样的类数组对象转换成jQuery对象,如果是函数,则改成DOM加载。

01. //@author  司徒正美|なさみ|cheng http://www.cnblogs.com/rubylouvre/ ; All rights reserved
02.     // Start with an empty selector
03.     selector: "",
04.     // The current version of jQuery being used
05.     jquery: "1.3.2",
06.     //返回jQuery对象所包裹的DOM对象的数量
07.     size: function() {
08.         return this.length;
09.     },
10.     //jQuery里面的方法都有一个特点,就是功能多
11.     //如著名的css,即是读方法也是写方法
12.     //这个可以返回一个纯数组
13.     //也可以返回一个纯净的DOM对象(根据索引值)
14.     get: function( num ) {
15.         return num === undefined ?
16.             // Return a 'clean' array
17.             Array.prototype.slice.call( this ) :
18.             // Return just the object
19.             this[ num ];
20.     },
01.     // Take an array of elements and push it onto the stack
02.     // (returning the new matched element set)
03.     pushStack: function( elems, name, selector ) {
04.         //创建一个新的jQuery对象
05.         var ret = jQuery( elems );
06.        //保存原来jQuery对象的引用
07.         ret.prevObject = this;
08.         //把原来的context移过来,context在jQuery通常用作搜索的新起点
09.         ret.context = this.context;
10.        //把selector标记为一个特殊的字符串,以后再解析为jQuery对象
11.         if ( name === "find" )
12.             ret.selector = this.selector + (this.selector ? " " : "") + selector;
13.         else if ( name )
14.             ret.selector = this.selector + "." + name + "(" + selector + ")";
15.         // Return the newly-formed element set
16.         return ret;
17.     },
18.   
19.     // Force the current matched set of elements to become
20.     // the specified array of elements (destroying the stack in the process)
21.     // You should use pushStack() in order to do this, but maintain the stack
22.     //把许多元素一并放置到新的jQuery对象中,由于用Array.prototype.push,不用自己维护长度
23.     setArray: function( elems ) {
24.         // Resetting the length to 0, then using the native Array push
25.         // is a super-fast way to populate an object with array-like properties
26.         this.length = 0;
27.         Array.prototype.push.apply( this, elems );
28.   
29.         return this;
30.     },
31.   
32.     // Execute a callback for every element in the matched set.
33.     // (You can seed the arguments with an array of args, but this is
34.     // only used internally.)
35.     //类似javascript1.6的forEach迭代器
36.     //这里是原型方法调用静态方法
37.     each: function( callback, args ) {
38.         return jQuery.each( this, callback, args );
39.     },
40.   
41.     //返回(DOM对象)elem在jQuery对象的位置(仅指数字键)
42.     //inArray的参数可以是jQuery对象,也可以是DOM对象
43.     //有点类似数组的indexOf
44.     index: function( elem ) {
45.         // Locate the position of the desired element
46.         return jQuery.inArray(
47.             // If it receives a jQuery object, the first element is used
48.             elem && elem.jquery ? elem[0] : elem
49.         , this );
50.     },
51. //这是个异常复杂的方法
52. //根据参数判断是读方法还是写方法
53.     attr: function( name, value, type ) {
54.         var options = name;
55.   
56.         // Look for the case where we're accessing a style value
57.         if ( typeof name === "string" )
58.             if ( value === undefined )
59.               //读方法,获取相应属性
60.                 return this[0] && jQuery[ type || "attr" ]( this[0], name );
61.   
62.             else {
63.               //写方法,设置相应属性
64.               //一个代理对象
65.                 options = {};
66.                 options[ name ] = value;
67.             }
68.   
69.         // Check to see if we're setting style values
70.         //真正是用其静态方法工作,静态方法的优先级是相当高的,排列如下:
71.         //foo.abc() 高于 this.abc()
72.         //构造函数内的 this.abc() 高于 原型方法foo.prototype.abc
73.         //极晚绑定 fooInstance.abc()是优先级最低
74.         return this.each(function(i){
75.             // Set all the styles
76.             for ( name in options )
77.                 jQuery.attr(
78.                     type ?
79.                         this.style :
80.                         this,
81.                     name, jQuery.prop( this, options[ name ], type, i, name )
82.                 );
83.         });
84.     },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值