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