上篇读到了jquery库如何通过其中的jQuery.extend及jQuery.fn.extend去扩展自身的。这篇将分析下jQuery.each及jQuery().each方法。看看他们如何与jQuery.extend一起扩展jquery库。查看源码,我们发现里面有10多处用到$.each及$().each。
jQuery1.4 已发布,后续将已1.4版本作为示例。部分源码如下:
jQuery.fn = jQuery.prototype = { ... each : function(callback, args){ return jQuery.each( this, callback, args ); } ... } jQuery.extend({ ... each : function(object, callback, args){ var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction(object); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call(object[name], name, object[name]) === false ){ break; } } } else { for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} } } return object; } ... });
以上可看出,
a,jQuery().each是直接挂在jQuery.prototype(jQuery.fn)上的,因此每个jquery对象都包含each方法。
b,jQuery.each是通过jQuery.extend({})方式扩展的。
上一篇已经说过,通过这种方式扩展的方法将挂在function jQuery上,即为jQuery类的静态方法。
c,jQuery().each方法中只有一句:return jQuery.each( this, callback, args )。
即jquery对象的each方法实现上其实就是调用jQuery静态的jQuery.each。因此jQuery.each才是关键所在。
下面详细分析jQuery.each。查看源码,jQuery.each方法有三个参数:object,callback,args
1:object可以为数组(Array),对象(Object),甚至是函数类型(Functoin);
2:callback是回调函数,类型为function;
3:args为jquery库自身使用,使用者不会用到该参数,这里暂不讨论该参数情况。
jQuery.each函数中第一句定义必要的变量:
var name, i = 0,length = object.length, isObj = length === undefined || jQuery.isFunction(object);
length=object.length很好理解,有三种情况length不为undefined。
a: object为数组类型(Array)时,数组具有length属性;
b: object为函数类型(Functoin)时,length为该函数定义的参数个数,如果该函数没有定义参数,length为0;
c: 具有length属性的object伪数组(如:arguments,HTMLCollection,NodeList等)。
这里特意强调下objcet为jquery对象。即当在$().each时发生,这时会将this传到$.each中。
如:return jQuery.each( this, callback, args )。这里第一个参数this即为jquery对象,每个jquery对象是具有length属性的。
变量isObj用来判断是否是对象类型,有两种情况为true:
1,变量length等于undefined,即所传object没有length属性。
2,参数object为函数类型
因为暂不考虑第三个参数args的情况(即这里只讨论不传args的情况),jQuery.each可简化为如下:
each : function(object, callback, args){ var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction(object); if ( isObj ) { for ( name in object ) { if ( callback.call(object[name], name, object[name]) === false ){ break; } } } else { for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} } return object; };
如果isObj为true,则用for in语句去遍历该对象,如果把每个迭代的对象看出键值对形式的话。callback中的this是值object[name],callback第一个参数是键name,第二个参数是值object[name]。
如果isObj为false,则用for循环去遍历数组(类数组)。callback中的this是数组中单独元素的值value,callback第一参数是数组的索引i,第二参数是数组单独元素值value。
callback调用后返回值如果是false则停止迭代,跳出循环。这里用严格"==="来判断是否与false相等。顺便提一下,函数如果没有显示的return,默认返回undefined。
最后总结下:
$().each的each是jquery对象的方法,实现上它调用静态的$.each。它只用来迭代jquery对象,jquery对象可以看成一个伪数组(具有length属性,用索引方式存取)。
$.each的each是function jQuery的静态方法,可以迭代对象,数组,伪数组,函数。