jQuery源码阅读3:each()方法

1.each有俩形式, 一是$.each的静态方法, 二是$(“XX”).each的原型方法.
内部实现是一份代码, $(“XX”)each会经过选择器包装对象, 而后调用$.each静态方法

2.具体实现上 each会处理两种情况, 一是处理对象, 二是处理数组类数组
都是callback.call( each内部遍历的当前项也就是替换this指针项, key, value )

3.$.each静态方法, 对于内部调用 接收第三个参数, 这个参数用于callback.apply, 其余和第2点一样

一:还是先看示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//1.数组的情况:对应 二.2
$("div").each(function(index, domEle){
$(this).text("div"+index);
});
//这两种写法等效, 源码237行相当于把上边的写法转成了这种写法
$.each($("div"),function(index, domEle){
$(this).text("div"+index);
});
//2.对象的情况:对应 二.3
var cosObj = {
a : "aa",
b : "bb",
c : function(){
alert("ruantao.duapp.com");
}
};
//遍历得到对象的各个属性
$.each(cosObj,function(name,value){
console.log("name==>"+name + "_value==>"+value);
});
//下边这样没法自动转化, 选择器会转成0: Object{a:,b:...}的结构, value拿到的是这个对象
$(cosObj).each(function(name,value){
console.log("name==>"+name + "_value==>"+value);
console.log("value.a==>"+value.a);
});

二:源码阅读:

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 博文作者:ruantao1989@gmail.com
* 引自博客:ruantao.duapp.com/blog
*/
//==>源码237行
//一:在jQuery.fn = jQuery.prototype里扩展的each()方法,
//1.这里这里转化了一下, 内部调用的jQuery.each是靠extend()添加的静态方法(添加过程之前分析过了)
//2.这里的this指的是产生的jQuery实例(反正是选择器生成的包装过的对象,类数组,有length,选择器太细节太多 回头再说...)
//3.args源码中注释:第三个参数仅内部使用,先不管
each: function( callback, args ) {
return jQuery.each( this, callback, args );
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//==>源码580行
//二:经过"一",传到这里
//1.obj是选择器生成的包装好的对象 , callback就是传入的回调函数, 可以是格式:function(index, domEle){});
each: function( obj, callback, args ) {
var name,
i = 0,
length = obj.length,
isObj = length === undefined || jQuery.isFunction( obj );
//源码中注释:第三个参数仅内部使用,这个先不管
// if ( args ) {
// if ( isObj ) {
// for ( name in obj ) {
// if ( callback.apply( obj[ name ], args ) === false ) {
// break;//如果在callback中返回false就跳出循环了
// }
// }
// } else {
// for ( ; i < length; ) {
// if ( callback.apply( obj[ i++ ], args ) === false ) {
// break;
// }
// }
// }
// A special, fast, case for the most common use of each
} else {
//3.这里判断是否是对象(看了下类型判断还不少, 下次分析)
//跟代码时候发现好多函数都调用此处进行扩展, 这儿的使用频率很高
if ( isObj ) {
for ( name in obj ) {
//用的for in去取对象属性, 其余和下边一样
if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
break;
}
}
} else {
//2.非对象的情况就是数组遍历
for ( ; i < length; ) {
//回调函数function(index, domEle){})调用call,
//也就是说回调里的this换成obj[ i ] (例如一个选择器返回的dom对象), 并且传入function( i, 该dom对象){})
//回调的内容$(this)就是jQuery(该dom对象)生成的实例
//最后i++, 另外如果回调返回false就可以break了
if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
break;
}
}
}
}
return obj;
}