讀jQuery之四(優雅的迭代)

前面提到jQuery庫如何經過其中的jQuery.extend及jQuery.fn.extend去擴展自身的。第三篇給zChain.js添加了經常使用選擇器,但目前爲止zChain.js仍然作不了任何事情。javascript

jQuery的操做每每是分兩步java

1,獲取元素集合(選擇器)數組

2,操做元素集合app

而第二步操做元素集合的主要方法就是jQuery.each。查看源碼,咱們發現jQuery.each及this.each分別調用了27次和31次。可見它是多麼的重要。函數

這篇將分析下jQuery.each及this.each方法。看看他們如何與jQuery.extend一塊兒擴展jQuery庫。最後我會給zChain.js加上each方法。

部分源碼以下this

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 ) {
         return  jQuery.each(  this , callback, args );
     },
     ...
}
 
jQuery.extend({
 
     ...
     // args is for internal usage only
     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  ( ; i < length; ) {
                     if  ( callback.call( object[ i ], i, object[ i++ ] ) ===  false  ) {
                         break ;
                     }
                 }
             }
         }
     
         return  object;
     }, 
     ...
});

 

以上可看出,
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庫自身使用,使用者不會用到該參數,這裏暫不討論該參數狀況。spa

 

函數中第一句定義必要的變量prototype

1
2
3
var  name, 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等)。code

 

變量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),能夠迭代對象,數組,僞數組,函數。

相關文章
相關標籤/搜索