jQuery 源码分析3: jQuery.fn/ jQuery.prototype
1 // 建立方法实例,提高方法访问的速度(避免在原型链上搜索) 2 3 var deletedIds = []; 4 var slice = deletedIds.slice; 5 var concat = deletedIds.concat; 6 var push = deletedIds.push; 7 var indexOf = deletedIds.indexOf; 8 var class2type = {}; 9 var toString = class2type.toString; 10 var hasOwn = class2type.hasOwnProperty; 11 var support = {}; 12 13 14 15 jQuery.fn = jQuery.prototype = { 16 // 保存目前jQuery版本号 17 jquery: version, 18 // 指向构造器 19 constructor: jQuery, 20 21 // 初始化空的选择器 22 selector: "", 23 24 // 初始化长度为0,及空的jQuery对象的length为0,可以此判断是否存在查找结果 25 length: 0, 26 // 转换成Array并返回 27 toArray: function() { 28 return slice.call( this ); // 使用了Array.slice 29 }, 30 31 // num == 0 则返回所有元素 32 33 // 如果 num < 0, 则返回第this.length + num个元素 34 get: function( num ) { 35 return num != null ? 36 // 返回一个元素 37 ( num < 0 ? this[ num + this.length ] : this[ num ] ) : 38 // 返回全部元素 39 slice.call( this ); 40 }, 41 42 // 将一个DOM元素集Array压入到jQuery栈 43 44 // 该方法在find,parent,filter中被频繁使用 45 46 // 通过创建prevObject,能够跟踪链式调用中上一个调用方法返回的元素集 47 pushStack: function( elems ) { 48 // 建立新的jQuery对象以保存新的元素集(将新元素集合并到其中) 49 var ret = jQuery.merge( this.constructor(), elems ); 50 // 新jQuery对象中创建prevObject,引用原来的jQuery对象,更新新元素集的上下文 51 ret.prevObject = this; 52 ret.context = this.context; 53 // 返回新的元素集 54 return ret; 55 }, 56 57 // 每个元素都调用一次回调函数,参数已Array形式传递(内部调用时才使用) 58 each: function( callback, args ) { 59 return jQuery.each( this, callback, args ); 60 }, 61 // jQuery.map对this中的每个key重新用回调函数计算出新的值并返回 62 63 // 将jQuery.map的返回结果添加到新的jQuery中并返回,新的jQuery以原有的元素为基础 64 map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { 65 return callback.call( elem, i, elem ); 66 })); 67 }, 68 // 通过slice将"参数数组"截取并压栈 69 slice: function() { 70 return this.pushStack( slice.apply( this, arguments ) ); 71 }, 72 // 将第一个元素压栈并返回新的jQuery栈 73 first: function() { 74 return this.eq( 0 ); 75 }, 76 // 将最后一个元素压栈并返回新的jQuery栈 77 last: function() { 78 return this.eq( -1 ); // 实际上是 len - 1, 即最后一个元素 79 }, 80 // 取this[i]并压栈,如果i < 0则取this[len + i],如果i > len, 压入空Array 81 eq: function( i ) { 82 var len = this.length, 83 j = +i + ( i < 0 ? len : 0 ); return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); 84 }, 85 // prevObject是通过pushStack创建的,通过end跟踪链式调用中上一个方法返回的DOM元素集 86 // end相当与一个出栈操作,通过end,能够返回到上一个链式调用方法的元素集,如 87 88 // $().find('button').click(function(){alert(1)}) // 对find('button')返回的元素操作 89 90 // .end().click(function(){alert(2)}) // 返回到find('button')返回的元素,然后操作 91 92 end: function() { 93 return this.prevObject || this.constructor(null); 94 }, 95 // 内部调用, 引用Array方法 96 push: push, 97 sort: deletedIds.sort, 98 splice: deletedIds.splice 99 };
这里定义了一个重要的方法————jQuery.pushStack;它在find,filter,parent等方法中被频繁使用。通过创建prevObject记录上次链式调用时返回的元素集结果,以此能够实现对链式调用元素集的跟踪,利用jQuery.end来回溯到上一次调用的结果。