Почему итерация объектов jQuery с .each() не дает мне объекты jQuery?
Следующее работает как ожидалось:
$(".foo").first().text("hi!")
... потому что first()
возвращает объект jQuery.
Однако, если я хочу работать с методом text()
для всех совпадений, мне нужно сделать:
$(".foo").each( function(idx, obj) {
$(obj).text("hi!")
}
)
... потому что each()
предоставляет объекты DOM.
Какова причина дизайна этой непонятной разницы? Как я могу избежать создания объекта jQuery для каждого соответствия?
Ответы
Ответ 1
Возможно, из-за причин производительности, связанных с циклом над большими коллекциями? Если вам нужны только объекты DOM, вы сохраняете циклы. Если вам нужен объект jQuery, вы можете легко получить это.
Обычно я не предоставляю второй параметр для каждого, поэтому я могу использовать $(this).
Ответ 2
Внутренне jQuery вызывает это для $("sel").each(function(){});
if ( isObj ) {
for ( name in object ) {
if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
break;
}
}
}
И eq
- простой срез:
eq: function( i ) {
return i === -1 ?
this.slice( i ) :
this.slice( i, +i + 1 );
}
Итак, вы можете создать новую функцию each
, которая вместо object[name]
сделает object:eq(i)
$("*").slice(1,2).toSource() == $("*").eq(1).toSource();
Итак, чтобы создать собственный each
:
$.fn.each2 = function(callback)
{
for ( var i = 0; i < this.length; ++i ) {
callback.call( this.eq(i), i, this.eq(i) )
}
};
$("*").each2(function(i, obj) {
alert(obj); // now obj is a jQuery object
});
Кажется, что each3
быстрее, чем each2
http://www.jsfiddle.net/m7pKk/2/
$.fn.each2 = function(callback)
{
for ( var i = 0; i < this.length; ++i ) {
var jObj = this.eq(i);
callback.call( jObj, i, jObj )
}
};
$.fn.each3 = function(callback)
{
for ( var i = 0; i < this.length; ++i ) {
var jObj = $(this[i]);
callback.call( jObj, i, jObj )
}
};
См. этот пример в jsFiddle с измерением производительности.
Ответ 3
Там будет очевидное достижение производительности, которое будет принято за итерацию. Создавая новый объект jQuery, каждая итерация будет намного медленнее и, вероятно, заметна над большими коллекциями. Довольно часто вам не нужно дополнительное удобство обернутого объекта, особенно при доступе к отдельным атрибутам или свойствам. Слишком часто вы видите код цикла, например $(this).is(":checked")
вместо this.checked
.
Кроме того, я бы сказал, что это потому, что это имеет смысл. Объект jQuery обычно представляет собой набор объектов DOM, которые могут быть любого числа в размере. Иногда jQuery используется исключительно для поддержки селектора и привязки событий и не намного выше этого. Не имеет смысла возвращать коллекцию, содержащую один элемент, при итерации по множеству элементов. Имеет смысл вернуться к одному элементу, который вам больше нужен, DOM-элементу, после чего вы можете обернуть его с помощью jQuery, если хотите добавить дополнительные функции. Это также поддерживает его в соответствии с итерацией по NodeList и другим типам коллекции.
Ответ 4
Вы видели . each vs jQuery.each
Вы должны быть в состоянии сделать следующее:
$('li').each(function(index) {
alert(index + ': ' + $(this).text());
});
по первой ссылке. Попробуйте $(this)
вместо $(obj)
Ответ 5
Try
$(".foo").each( function(idx, obj) {
$(this).text("hi!")
}
)
Ответ 6
Я считаю, что, поскольку jQuery использует объекты-оболочки, первый метод использует исходную оболочку и просто удаляет все, кроме первого элемента в оболочке, тем самым сохраняя его как объект jQuery.
Однако, если они должны были подавать объект jQuery для каждого из узлов для функции each()
, они будут нести накладные расходы на создание обертки для каждого из них. И поскольку вам не обязательно нужен этот объект-оболочка, он будет нести лишние накладные расходы.
Ответ 7
Наверное, потому что в вашем примере нет причин даже использовать each
. Вместо:
$(".foo").each( function(idx, obj) {
$(obj).text("hi!");
)
Просто используйте:
$(".foo").text("hi!");
Все происходит автоматически во множественном числе при работе с наборами jQuery.