Jquery的$(selector).each()和$.each()原理和區別

洞拐洞拐發表於2016-10-13

  我們都用過Jqurey中的each函式,都知道each()有兩種方式去呼叫,一種是通過$.each()呼叫,另一種是$(selector).each()去呼叫,那麼它們之間有什麼區別?

  翻看一下Jquery原始碼就會知道,$.each()是核心的實現,$(selector).each()是呼叫的$.each(),先來分析一下$.each()的原始碼(在底部):

    each(obj,callback,args)函式接收3個引數:obj--要遍歷的物件或陣列、callback--要遍歷執行的回撥函式、args--自己指定的陣列(先無視)。

 

  1.沒有args的情況

    一般來說,args是不常用的,所以先不討論當if(args)成立的情況,也就是直接看在程式碼中標為灰色的部分,這也是each()函式核心的部分

   if(isArray) {
      for(; i < length; i++) {
        value = callback.call(obj[i], i, obj[i]);
        if(value === false) { break; }
      }
    }
   如果你要遍歷的物件,是陣列型別,則進入此程式碼塊
   for迴圈遍歷陣列的每個元素,然後利用call方法,執行obj[i].callback(i,obj[i]),
   所以,自己再寫回撥函式的時候,應該意識到jquery會用陣列的每個物件去執行你的回撥函式,引數傳的是元素在陣列中index和該元素,同時回撥方法內部的this,也指向該元素;
   下一行是判斷回撥函式是否返回了值,如果回撥函式返回false,則跳出該陣列的迴圈。

  如果自己傳的物件也是可以遍歷的,程式碼和上面陣列遍歷也是一樣的

   else {
      for(i in obj) {
          value = callback.call(obj[i], i, obj[i]);
          if(value === false) { break; }
        }
    }
   如果自己傳的是物件,則用for(x in y)遍歷物件的屬性,
   原理和上面一樣,只不過換成物件內部的屬性x,去執行回撥函式,相當於obj.attr.callback(i,obj.attr);
   回掉函式中如果返回false,也是會結束迴圈操作。

  2.有args的情況

  當呼叫each()有第三個引數的時候,便會進入下面的程式碼塊,來分析下:

    if(isArray) {
            for(; i < length; i++) {
                value = callback.apply(obj[i], args);
                if(value === false) { break; }
            }
        } else {
            for(i in obj) {
                value = callback.apply(obj[i], args);
                if(value === false) { break; }
            }
        }
    同樣道理,會先判斷你要遍歷的物件是否是陣列,如果是陣列,則遍歷陣列的元素obj[i],並執行obj[i].callback(args)
    注意!這個地方傳的引數是你自己傳進來的args陣列,這是和沒有args引數不一樣的地方,也就是說如果你呼叫each函式是傳入了自己的陣列引數,回撥函式的引數列表就是你所傳的args陣列。
    其他的同上。
  還有大家注意到了沒有?有args和沒有args的區別就是一個用了apply(),而另一個用了call(),這兒簡單記一下他倆的區別:

  Apply():While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts anargument list,while apply() accepts a single array of arguments. --引自MDN

  翻譯一下就是:雖然這個apply()和call()句法幾乎一致,但是有一個重要的區別就是call()函式是接受多個引數,而apply()僅僅接受一個陣列物件。

  $(selector).each(callback,args)函式接收2個引數:callback--要遍歷執行的回撥函式、args--自己指定的陣列。

 

  明白了$.each()函式,$(selector).each就簡單了,翻開原始碼,$(selector).each內部就是呼叫的$.each()函式,原始碼如下:

  each: function( callback, args ) {
      return jQuery.each( this, callback, args );
  },

  可以看到,在呼叫$.each()的時候,obj引數是寫成了this,也就是$(selector),這是jquery選擇器返回一個jquery內部物件。

  

  總結:$.each()$(selector).each()的區別就是前者可以針對所有物件或者陣列進行遍歷,而後者是針對jquery選擇器返回的jquery內部物件進行遍歷,前者更強大一些

 

  

  附上原始碼

 //Jquery中$.each()的原始碼
 each: function(obj, callback, args) { var value,i = 0, length = obj.length, isArray = isArraylike(obj); if(args) { if(isArray) { for(; i < length; i++) { value = callback.apply(obj[i], args); if(value === false) { break; } } } else { for(i in obj) { value = callback.apply(obj[i], args); if(value === false) { break; } } } // A special, fast, case for the most common use of each } else { if(isArray) { for(; i < length; i++) { value = callback.call(obj[i], i, obj[i]); if(value === false) { break; } } } else { for(i in obj) { value = callback.call(obj[i], i, obj[i]); if(value === false) { break; } } } }

 

相關文章