为什么用.each()迭代jQuery对象不给我jQuery对象?

时间:2010-10-16 15:13:54

标签: jquery

以下按预期方式工作:

$(".foo").first().text("hi!")

...因为first()返回一个jQuery对象。

但是,如果我想对所有匹配使用text()方法,我需要这样做:

$(".foo").each( function(idx, obj) {
  $(obj).text("hi!")
  }
)

...因为each()为您提供了DOM对象。

这种莫名其妙的差异背后的设计原因是什么?我怎样才能避免为每个匹配构建一个jQuery对象?

7 个答案:

答案 0 :(得分:12)

可能是由于与循环大型集合相关的性能原因造成的?如果您只需要DOM对象,则可以节省周期。如果你需要jQuery对象,那么你可以很容易地得到它。

我通常不为每个提供第二个参数,所以我可以使用$(this)。

答案 1 :(得分:3)

内部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
});

似乎each3each2 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 )
   }
};

<强> See this example on jsFiddle with performance measurement.

答案 2 :(得分:2)

每次迭代都会有明显的性能损失。每次迭代创建一个新的jQuery对象会慢很多,并且可能在大型集合中很明显。通常,您不需要包装对象的额外便利性,尤其是在访问单个属性或属性时。您经常会看到循环浪费代码$(this).is(":checked")而不是this.checked

除此之外,我会说它是因为它有意义。 jQuery对象通常表示DOM对象的集合,可以是任何数量的大小。有时jQuery纯粹用于它的选择器支持和事件绑定,并没有太多。在迭代更多元素的集合时返回包含单个元素的集合没有多大意义。返回一个你更可能需要的单个项目(DOM元素)更有意义,如果你想要添加的功能,你可以用jQuery包装它。这也使它与迭代NodeList和其他类型的集合保持一致。

答案 3 :(得分:1)

我相信,由于jQuery使用包装器对象,第一种方法使用原始包装器,只删除包装器中除第一个元素之外的所有元素,从而使它成为jQuery对象。

但是,如果它们为each()函数的每个节点提供jQuery对象,则会产生为每个节点创建包装器的开销。由于您不一定需要该包装器对象,因此会产生不必要的开销。

答案 4 :(得分:0)

可能是因为,在您的示例中,没有理由使用each。而不是:

$(".foo").each( function(idx, obj) {
  $(obj).text("hi!");
)

只需使用:

$(".foo").text("hi!");

处理jQuery集时,一切都是自动复数。

答案 5 :(得分:-1)

您是否看到.each vs jQuery.each

您应该能够执行以下操作:

$('li').each(function(index) {
    alert(index + ': ' + $(this).text());
});

按照第一个链接。请尝试使用$(this)代替$(obj)

答案 6 :(得分:-1)

尝试

$(".foo").each( function(idx, obj) {
  $(this).text("hi!")
  }
)