我們都用過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; } } } }