赞助商
不知该起什么题目,随便吧。不过我没心情逐一介绍其API,那是文档的事。比起那些随时会被废弃的方法,我更着重其内在的技术,所以我选择读源码。由于我从不用jQuery,可能理解有些偏差。不过,看了这么多类库,有许多东西都是共通。比如这个jQuery对象就是DOM对象的加工工场,把DOM 对象包裹其中,外围是许多便捷的方法。我们可以想象一下太阳系,DOM就是太阳,css就其中一个行星,attr是另一个……之所以选择类数组形式,是为了用map,filter等发端于数组的同名方法进行大数量的DOM操作。好了,下面就直接写在注解中吧。(文/司徒正美
  1. 01.var
  2. 02.window = this,
  3. 03.undefined,
  4. 04._jQuery = window.jQuery,
  5. 05._$ = window.$,
  6. 06.//把window存入闭包中的同名变量,undefined的情形一样,的确是让更内围的作用域的方法调用时,不要跑到那么远
  7. 07.//不过undefined在IE5之前不支持,很多类库都使用以下语句代替
  8. 08.//window.undefined = void 0
  9. 09.//因此这处John Resig就做得不好了
  10. 10.//_jQuery与_$用于以后重写
  11. 11.jQuery = window.jQuery = window.$ = function( selector, context ) {
  12. 12.  //用于返回一个jQuery对象
  13. 13.  return new jQuery.fn.init( selector, context );
  14. 14.},
  15. 15.//这东西看起来很唬人,其实就是想获取元素的标签名或ID
  16. 16.quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
  17. 17.//检测是否一个简单的选择器,怎样才为之简单呢?
  18. 18.//就是一重类选择器,也就是这个样子.red,如果.red .dd就不合要求了
  19. 19.//看它的限制,一定要是类选择器,后面不能跟伪类选择器,ID选择器,属性选择器,第二重第三重的类选择器
  20. 20.//与并联选择器
  21. 21.isSimple = /^.[^:#\[\.,]*$/;
复制代码
  1. 01.jQuery.fn = jQuery.prototype = {
  2. 02.  init: function( selector, context ) {
  3. 03.    //如果为空就把document塞进jQuery对象中
  4. 04.    selector = selector || document;
  5. 05.    //如果第一个参数是DOM对象,那它肯定有nodeType吧,
  6. 06.    //是就开始创建索引,创建类数组对象
  7. 07.    //说白了就是一个hash,只不过键是数字,值是DOM对象
  8. 08.    //不过它除了[0],[1]等数字键外,还有"css","attr","addClass"等字符串键,它们的值对应方法
  9. 09.    //length属性是就Array.prototype.slice与map,filter等方法准备
  10. 10.    //this.context是作为下次搜索的起点,如DOMElement.getElementsByTagName("span")
  11. 11.    if ( selector.nodeType ) {
  12. 12.      this[0] = selector;
  13. 13.      this.length = 1;
  14. 14.      this.context = selector;
  15. 15.      return this;
  16. 16.    }
  17. 17.    //如果传入的是CSS selector字段
  18. 18.    if ( typeof selector === "string" ) {
  19. 19.      //如果是很单的tagName或ID
  20. 20.      var match = quickExpr.exec( selector );
  21. 21.      //选择器类似h1的情形     
  22. 22.      if ( match && (match[1] || !context) ) {
  23. 23.        //如果是标签
  24. 24.        if ( match[1] )
  25. 25.        //clean方法不厚道地放到800行之后,针对许多特殊情况做处理
  26. 26.          selector = jQuery.clean( [ match[1] ], context );
  27. 27.        // HANDLE: $("#id")
  28. 28.        else { 
  29. 29.          var elem = document.getElementById( match[3] );
  30. 30.
  31. 31.          // Handle the case where IE and Opera return items
  32. 32.          // by name instead of ID
  33. 33.          //在IE与Opera中,ID并不一定返回一个元素,这时用name来查找
  34. 34.          if ( elem && elem.id != match[3] )
  35. 35.            return jQuery().find( selector );
  36. 36.
  37. 37.          //由于ID有排他性,因此需要清空前面的context,     
  38. 38.          var ret = jQuery( elem || [] );
  39. 39.          //重设搜索起点,
  40. 40.          ret.context = document;
  41. 41.          //安装DOM对象
  42. 42.          ret.selector = selector;
  43. 43.          return ret;
  44. 44.        }
  45. 45.
  46. 46.        // HANDLE: $(expr, [context])
  47. 47.        // (which is just equivalent to: $(content).find(expr)
  48. 48.      } else
  49. 49.      //处理非常复杂的选择器,如镶嵌的CSS3选择器
  50. 50.        return jQuery( context ).find( selector );
  51. 51.
  52. 52.      // HANDLE: $(function)
  53. 53.      // Shortcut for document ready
  54. 54.      //著名的DOMReady的,就是美元符号里面传入一个匿名函数
  55. 55.    } else if ( jQuery.isFunction( selector ) )
  56. 56.      return jQuery( document ).ready( selector );
  57. 57.
  58. 58.    // Make sure that old selector state is passed along
  59. 59.    if ( selector.selector && selector.context ) {
  60. 60.      this.selector = selector.selector;
  61. 61.      this.context = selector.context;
  62. 62.    }
  63. 63.    //确保以jQuery的类数组对象返回
  64. 64.    return this.setArray(jQuery.isArray( selector ) ?
  65. 65.      selector :
  66. 66.      jQuery.makeArray(selector));
  67. 67.  },
复制代码
基本上init就是个大熔炉,根据传入参数的类型做出不同的处理,如DOM对象,字符串,数组对象与NodeList这样的类数组对象转换成jQuery对象,如果是函数,则改成DOM加载。
  1. 01.// Start with an empty selector
  2. 02.selector: "",
  3. 03.// The current version of jQuery being used
  4. 04.jquery: "1.3.2",
  5. 05.//返回jQuery对象所包裹的DOM对象的数量
  6. 06.size: function() {
  7. 07.    return this.length;
  8. 08.},
  9. 09.//jQuery里面的方法都有一个特点,就是功能多
  10. 10.//如著名的css,即是读方法也是写方法
  11. 11.//这个可以返回一个纯数组
  12. 12.//也可以返回一个纯净的DOM对象(根据索引值)
  13. 13.get: function( num ) {
  14. 14.    return num === undefined ?
  15. 15.        // Return a 'clean' array
  16. 16.        Array.prototype.slice.call( this ) :
  17. 17.        // Return just the object
  18. 18.        this[ num ];
  19. 19.},
复制代码
  1. 01.    // Take an array of elements and push it onto the stack
  2. 02.    // (returning the new matched element set)
  3. 03.    pushStack: function( elems, name, selector ) {
  4. 04.        //创建一个新的jQuery对象
  5. 05.        var ret = jQuery( elems );
  6. 06.      //保存原来jQuery对象的引用
  7. 07.        ret.prevObject = this;
  8. 08.        //把原来的context移过来,context在jQuery通常用作搜索的新起点
  9. 09.        ret.context = this.context;
  10. 10.      //把selector标记为一个特殊的字符串,以后再解析为jQuery对象
  11. 11.        if ( name === "find" )
  12. 12.            ret.selector = this.selector + (this.selector ? " " : "") + selector;
  13. 13.        else if ( name )
  14. 14.            ret.selector = this.selector + "." + name + "(" + selector + ")";
  15. 15.        // Return the newly-formed element set
  16. 16.        return ret;
  17. 17.    },
  18. 18.
  19. 19.    // Force the current matched set of elements to become
  20. 20.    // the specified array of elements (destroying the stack in the process)
  21. 21.    // You should use pushStack() in order to do this, but maintain the stack
  22. 22.    //把许多元素一并放置到新的jQuery对象中,由于用Array.prototype.push,不用自己维护长度
  23. 23.    setArray: function( elems ) {
  24. 24.        // Resetting the length to 0, then using the native Array push
  25. 25.        // is a super-fast way to populate an object with array-like properties
  26. 26.        this.length = 0;
  27. 27.        Array.prototype.push.apply( this, elems );
  28. 28.
  29. 29.        return this;
  30. 30.    },
  31. 31.
  32. 32.    // Execute a callback for every element in the matched set.
  33. 33.    // (You can seed the arguments with an array of args, but this is
  34. 34.    // only used internally.)
  35. 35.    //类似javascript1.6的forEach迭代器
  36. 36.    //这里是原型方法调用静态方法
  37. 37.    each: function( callback, args ) {
  38. 38.        return jQuery.each( this, callback, args );
  39. 39.    },
  40. 40.
  41. 41.    //返回(DOM对象)elem在jQuery对象的位置(仅指数字键)
  42. 42.    //inArray的参数可以是jQuery对象,也可以是DOM对象
  43. 43.    //有点类似数组的indexOf
  44. 44.    index: function( elem ) {
  45. 45.        // Locate the position of the desired element
  46. 46.        return jQuery.inArray(
  47. 47.            // If it receives a jQuery object, the first element is used
  48. 48.            elem && elem.jquery ? elem[0] : elem
  49. 49.        , this );
  50. 50.    },
  51. 51.//这是个异常复杂的方法
  52. 52.//根据参数判断是读方法还是写方法
  53. 53.    attr: function( name, value, type ) {
  54. 54.        var options = name;
  55. 55.
  56. 56.        // Look for the case where we're accessing a style value
  57. 57.        if ( typeof name === "string" )
  58. 58.            if ( value === undefined )
  59. 59.              //读方法,获取相应属性
  60. 60.                return this[0] && jQuery[ type || "attr" ]( this[0], name );
  61. 61.
  62. 62.            else {
  63. 63.              //写方法,设置相应属性
  64. 64.              //一个代理对象
  65. 65.                options = {};
  66. 66.                options[ name ] = value;
  67. 67.            }
  68. 68.
  69. 69.        // Check to see if we're setting style values
  70. 70.        //真正是用其静态方法工作,静态方法的优先级是相当高的,排列如下:
  71. 71.        //foo.abc() 高于 this.abc()
  72. 72.        //构造函数内的 this.abc() 高于 原型方法foo.prototype.abc
  73. 73.        //极晚绑定 fooInstance.abc()是优先级最低
  74. 74.        return this.each(function(i){
  75. 75.            // Set all the styles
  76. 76.            for ( name in options )
  77. 77.                jQuery.attr(
  78. 78.                    type ?
  79. 79.                        this.style :
  80. 80.                        this,
  81. 81.                    name, jQuery.prop( this, options[ name ], type, i, name )
  82. 82.                );
  83. 83.        });
  84. 84.    },
复制代码
赞助商
赞助商
TOP