读jQuery之四,优雅的迭代

前面提到jQuery库如何通过其中的jQuery.extend及jQuery.fn.extend去扩展自身的。第三篇给zChain.js添加了常用选择器,但目前为止zChain.js仍然做不了任何事情。

jQuery的操作往往是分两步

1,获取元素集合(选择器)

2,操作元素集合

而第二步操作元素集合的主要方法就是jQuery.each。查看源码,我们发现jQuery.each及this.each分别调用了27次和31次。可见它是多么的重要。

这篇将分析下jQuery.each及this.each方法。看看他们如何与jQuery.extend一起扩展jQuery库。最后我会给zChain.js加上each方法。

部分源码如下

?

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

53

54

55

jQuery.fn = jQuery.prototype = {

...

// Execute a callback for every element in the matched set.

// (You can seed the arguments with an array of args, but this is

// only used internally.)

each:function( callback, args ) {

returnjQuery.each(this, callback, args );

},

...

}

jQuery.extend({

...

// args is for internal usage only

each:function( object, callback, args ) {

varname, i = 0,

length = object.length,

isObj = length === undefined || jQuery.isFunction( object );

if( args ) {

if( isObj ) {

for( nameinobject ) {

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( nameinobject ) {

if( callback.call( object[ name ], name, object[ name ] ) ===false) {

break;

}

}

}else{

for( ; i < length; ) {

if( callback.call( object[ i ], i, object[ i++ ] ) ===false) {

break;

}

}

}

}

returnobject;

},

...

});

以上可看出,

1,jQuery().each是直接挂在jQuery.prototype(jQuery.fn)上的,因此每个jQuery对象都包含each方法。

2,jQuery.each是通过jQuery.extend({})方式扩展的。前面已经说过,通过这种方式扩展的方法将挂在function jQuery上,即为jQuery类的静态方法。

3,jQuery().each方法中只有一句:return jQuery.each( this, callback, args )。即jQuery对象的each方法实现上其实就是调用jQuery静态的jQuery.each。因此jQuery.each才是关键所在。

下面详细分析jQuery.each,它有三个参数object, callback, args。

1,object可以为数组(Array),对象(Object),甚至是函数类型(Functoin);

2,callback是回调函数,类型为function;

3,args为jQuery库自身使用,使用者不会用到该参数,这里暂不讨论该参数情况。

函数中第一句定义必要的变量

?

1

2

3

varname, i = 0,

length = object.length,

isObj = length === undefined || jQuery.isFunction( object );

length=object.length很好理解,有三种情况length不为undefined

1, object为数组类型(Array)时,数组具有length属性;

2, object为函数类型(Functoin)时,length为该函数定义的参数个数,如果该函数没有定义参数,length为0;

3, 具有length属性的object伪数组(如:arguments,HTMLCollection,NodeList等)。

变量isObj用来判断是否是对象类型,有两种情况为true:

1,变量length等于undefined,即所传object没有length属性。

2,参数object为函数类型

这里强调下object为jQuery对象。即当在$(xx).each时发生,这时会将this传到$.each中。如:return jQuery.each( this, callback, args )。这里第一个参数this即为jQuery对象,每个jQuery对象是具有length属性的。

each中有以下两个分支

1,如果isObj为true,则用for in语句去遍历该对象,如果把每个迭代的对象看出键值对形式的话。callback中的this是值object[name],callback第一个参数是键name,第二个参数是值object[name]。

2,如果isObj为false,则用for循环去遍历数组(类数组)。callback中的this是数组中单独元素的值value,callback第一参数是数组的索引i,第二参数是数组单独元素值value。

callback调用后返回值如果是false则停止迭代,跳出循环。这里用严格"==="来判断是否与false相等。顺便提一下,函数如果没有显示的return,默认返回undefined。

总结下:

1,$(xx).each的each是jQuery对象的方法,它调用静态的jQuery.each。它只用来迭代jQuery对象,jQuery对象可以看成一个伪数组(具有length属性,用索引方式存取)。

2,$.each的each是function jQuery的静态方法(即jQuery.each),可以迭代对象,数组,伪数组,函数。

前面提到jQuery库如何通过其中的jQuery.extend及jQuery.fn.extend去扩展自身的。第三篇给zChain.js添加了常用选择器,但目前为止zChain.js仍然做不了任何事情。

jQuery的操作往往是分两步

1,获取元素集合(选择器)

2,操作元素集合

而第二步操作元素集合的主要方法就是jQuery.each。查看源码,我们发现jQuery.each及this.each分别调用了27次和31次。可见它是多么的重要。

这篇将分析下jQuery.each及this.each方法。看看他们如何与jQuery.extend一起扩展jQuery库。最后我会给zChain.js加上each方法。

部分源码如下

?

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

53

54

55

jQuery.fn = jQuery.prototype = {

...

// Execute a callback for every element in the matched set.

// (You can seed the arguments with an array of args, but this is

// only used internally.)

each:function( callback, args ) {

returnjQuery.each(this, callback, args );

},

...

}

jQuery.extend({

...

// args is for internal usage only

each:function( object, callback, args ) {

varname, i = 0,

length = object.length,

isObj = length === undefined || jQuery.isFunction( object );

if( args ) {

if( isObj ) {

for( nameinobject ) {

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( nameinobject ) {

if( callback.call( object[ name ], name, object[ name ] ) ===false) {

break;

}

}

}else{

for( ; i < length; ) {

if( callback.call( object[ i ], i, object[ i++ ] ) ===false) {

break;

}

}

}

}

returnobject;

},

...

});

以上可看出,

1,jQuery().each是直接挂在jQuery.prototype(jQuery.fn)上的,因此每个jQuery对象都包含each方法。

2,jQuery.each是通过jQuery.extend({})方式扩展的。前面已经说过,通过这种方式扩展的方法将挂在function jQuery上,即为jQuery类的静态方法。

3,jQuery().each方法中只有一句:return jQuery.each( this, callback, args )。即jQuery对象的each方法实现上其实就是调用jQuery静态的jQuery.each。因此jQuery.each才是关键所在。

下面详细分析jQuery.each,它有三个参数object, callback, args。

1,object可以为数组(Array),对象(Object),甚至是函数类型(Functoin);

2,callback是回调函数,类型为function;

3,args为jQuery库自身使用,使用者不会用到该参数,这里暂不讨论该参数情况。

函数中第一句定义必要的变量

?

1

2

3

varname, i = 0,

length = object.length,

isObj = length === undefined || jQuery.isFunction( object );

length=object.length很好理解,有三种情况length不为undefined

1, object为数组类型(Array)时,数组具有length属性;

2, object为函数类型(Functoin)时,length为该函数定义的参数个数,如果该函数没有定义参数,length为0;

3, 具有length属性的object伪数组(如:arguments,HTMLCollection,NodeList等)。

变量isObj用来判断是否是对象类型,有两种情况为true:

1,变量length等于undefined,即所传object没有length属性。

2,参数object为函数类型

这里强调下object为jQuery对象。即当在$(xx).each时发生,这时会将this传到$.each中。如:return jQuery.each( this, callback, args )。这里第一个参数this即为jQuery对象,每个jQuery对象是具有length属性的。

each中有以下两个分支

1,如果isObj为true,则用for in语句去遍历该对象,如果把每个迭代的对象看出键值对形式的话。callback中的this是值object[name],callback第一个参数是键name,第二个参数是值object[name]。

2,如果isObj为false,则用for循环去遍历数组(类数组)。callback中的this是数组中单独元素的值value,callback第一参数是数组的索引i,第二参数是数组单独元素值value。

callback调用后返回值如果是false则停止迭代,跳出循环。这里用严格"==="来判断是否与false相等。顺便提一下,函数如果没有显示的return,默认返回undefined。

总结下:

1,$(xx).each的each是jQuery对象的方法,它调用静态的jQuery.each。它只用来迭代jQuery对象,jQuery对象可以看成一个伪数组(具有length属性,用索引方式存取)。

2,$.each的each是function jQuery的静态方法(即jQuery.each),可以迭代对象,数组,伪数组,函数。