发布日期:
2009-11-20 12:13 发布者: cobra
原版编程图书超低价热卖
1#
t
T
不知该起什么题目,随便吧。不过我没心情逐一介绍其API,那是文档的事。比起那些随时会被废弃的方法,我更着重其内在的技术,所以我选择读源码。由于我从不用jQuery,可能理解有些偏差。不过,看了这么多类库,有许多东西都是共通。比如这个jQuery对象就是DOM对象的加工工场,把DOM 对象包裹其中,外围是许多便捷的方法。我们可以想象一下太阳系,DOM就是太阳,css就其中一个行星,attr是另一个……之所以选择类数组形式,是为了用map,filter等发端于数组的同名方法进行大数量的DOM操作。好了,下面就直接写在注解中吧。(文/ 司徒正美) - 01.var
- 02.window = this,
- 03.undefined,
- 04._jQuery = window.jQuery,
- 05._$ = window.$,
- 06.//把window存入闭包中的同名变量,undefined的情形一样,的确是让更内围的作用域的方法调用时,不要跑到那么远
- 07.//不过undefined在IE5之前不支持,很多类库都使用以下语句代替
- 08.//window.undefined = void 0
- 09.//因此这处John Resig就做得不好了
- 10.//_jQuery与_$用于以后重写
- 11.jQuery = window.jQuery = window.$ = function( selector, context ) {
- 12. //用于返回一个jQuery对象
- 13. return new jQuery.fn.init( selector, context );
- 14.},
- 15.//这东西看起来很唬人,其实就是想获取元素的标签名或ID
- 16.quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
- 17.//检测是否一个简单的选择器,怎样才为之简单呢?
- 18.//就是一重类选择器,也就是这个样子.red,如果.red .dd就不合要求了
- 19.//看它的限制,一定要是类选择器,后面不能跟伪类选择器,ID选择器,属性选择器,第二重第三重的类选择器
- 20.//与并联选择器
- 21.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.
- 31. // Handle the case where IE and Opera return items
- 32. // by name instead of ID
- 33. //在IE与Opera中,ID并不一定返回一个元素,这时用name来查找
- 34. if ( elem && elem.id != match[3] )
- 35. return jQuery().find( selector );
- 36.
- 37. //由于ID有排他性,因此需要清空前面的context,
- 38. var ret = jQuery( elem || [] );
- 39. //重设搜索起点,
- 40. ret.context = document;
- 41. //安装DOM对象
- 42. ret.selector = selector;
- 43. return ret;
- 44. }
- 45.
- 46. // HANDLE: $(expr, [context])
- 47. // (which is just equivalent to: $(content).find(expr)
- 48. } else
- 49. //处理非常复杂的选择器,如镶嵌的CSS3选择器
- 50. return jQuery( context ).find( selector );
- 51.
- 52. // HANDLE: $(function)
- 53. // Shortcut for document ready
- 54. //著名的DOMReady的,就是美元符号里面传入一个匿名函数
- 55. } else if ( jQuery.isFunction( selector ) )
- 56. return jQuery( document ).ready( selector );
- 57.
- 58. // Make sure that old selector state is passed along
- 59. if ( selector.selector && selector.context ) {
- 60. this.selector = selector.selector;
- 61. this.context = selector.context;
- 62. }
- 63. //确保以jQuery的类数组对象返回
- 64. return this.setArray(jQuery.isArray( selector ) ?
- 65. selector :
- 66. jQuery.makeArray(selector));
- 67. },
复制代码基本上init就是个大熔炉,根据传入参数的类型做出不同的处理,如DOM对象,字符串,数组对象与NodeList这样的类数组对象转换成jQuery对象,如果是函数,则改成DOM加载。 - 01.// Start with an empty selector
- 02.selector: "",
- 03.// The current version of jQuery being used
- 04.jquery: "1.3.2",
- 05.//返回jQuery对象所包裹的DOM对象的数量
- 06.size: function() {
- 07. return this.length;
- 08.},
- 09.//jQuery里面的方法都有一个特点,就是功能多
- 10.//如著名的css,即是读方法也是写方法
- 11.//这个可以返回一个纯数组
- 12.//也可以返回一个纯净的DOM对象(根据索引值)
- 13.get: function( num ) {
- 14. return num === undefined ?
- 15. // Return a 'clean' array
- 16. Array.prototype.slice.call( this ) :
- 17. // Return just the object
- 18. this[ num ];
- 19.},
复制代码- 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. },
复制代码
|