以下按预期方式工作:
$(".foo").first().text("hi!")
...因为first()
返回一个jQuery对象。
但是,如果我想对所有匹配使用text()
方法,我需要这样做:
$(".foo").each( function(idx, obj) {
$(obj).text("hi!")
}
)
...因为each()
为您提供了DOM对象。
这种莫名其妙的差异背后的设计原因是什么?我怎样才能避免为每个匹配构建一个jQuery对象?
答案 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
});
似乎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 )
}
};
<强> 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!")
}
)