为什么用.each()迭代jQuery对象不给我jQuery对象?
预期以下工作:为什么用.each()迭代jQuery对象不给我jQuery对象?
$(".foo").first().text("hi!")
...因为first()
返回一个jQuery对象。
但是,如果我想对所有比赛的text()
方法来工作,我需要做的:
$(".foo").each(function(idx, obj) {
$(obj).text("hi!")
}
)
...因为each()
给你DOM对象。
这个令人困惑的区别背后的设计原因是什么?我该如何避免为每个匹配构建一个jQuery对象?
可能由于涉及到遍历大集合性能方面的原因?如果您只需要DOM对象,则可以节省周期。如果你需要jQuery对象,那么你可以很容易地得到它。
我通常不会为每个参数提供第二个参数,所以我可以使用$(this)。
你看到.each VS jQuery.each
你应该能够做到以下几点:
$('li').each(function(index) {
alert(index + ': ' + $(this).text());
});
%的第一个链接。尝试$(this)
代替$(obj)
这是没有意义的方式不同。我仍然需要制作jQuery对象。 – badp 2010-10-16 15:28:15
尝试
$(".foo").each(function(idx, obj) {
$(this).text("hi!")
}
)
'$()'构造函数仍然存在。 – badp 2010-10-16 15:29:13
我相信,由于jQuery使用包装对象,第一个方法使用原始包装,并只删除包装中的第一个元素,从而保持它为jQuery对象。
但是,如果他们为每个节点提供了一个jQuery对象,那么它们会产生为每个节点创建包装的开销。由于你不一定需要这个包装器对象,它会产生不必要的开销。
内部的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)
}
};
所以[this](http://gist.github.com/629941)也能工作吗? :)此外,我现在需要做一些分析,以了解哪一个更快。 – badp 2010-10-16 15:55:02
@badp:是的。我认为'obj [i]'和'obj.slice(i,i + 1)'没有太大区别......参见这里的示例http://www.jsfiddle.net/m7pKk/ – BrunoLM 2010-10-16 16:02:55
@ BrunoLM,实际上'$(“.foo”)[i]'返回一个DOM对象,而'$(“.foo”)。eq(i)'给出一个jQuery对象。这里的要点非常重要,并且通过切片实现'eq',我几乎相信'$($(“。foo”)[i])'会更快...... – badp 2010-10-16 16:07:46
有明显的性能损失,这将是采取每次迭代。每次迭代创建一个新的jQuery对象比较大的集合要慢得多并且可能很明显。通常,您不需要包装对象的附加便利,特别是在访问单个属性或属性时。您经常会看到像$(this).is(":checked")
这样的周期浪费代码,而不是this.checked
。
除此之外,我会说这是因为它有意义。一个jQuery对象通常代表可以是任何数量的DOM对象的集合。有时候,jQuery纯粹用于选择器支持和事件绑定,并没有太多。迭代包含单个元素的集合时,迭代多个元素的集合时没有多大意义。返回更可能需要的单个项目(DOM元素)会更有意义,如果您需要添加的功能,则可以使用jQuery来包装它。这也保持了对NodeList和其他类型集合的迭代。
可能是因为在你的例子中没有理由甚至使用each
。相反的:
$(".foo").each(function(idx, obj) {
$(obj).text("hi!");
)
只需使用:使用jQuery集时
$(".foo").text("hi!");
一切都是自动复数。
正是我想说的,再加上如果first()没有返回一个jQuery对象,你将不得不使用$($(selector).first()),这与jQuery的简洁目标有些冲突。 – 2010-10-16 15:25:48
好吧,我的印象是,$(“。foo”)让jQuery对象以_开头,当它们通过'each()'时,它们被分解为“基本”DOM对象。我想这不是什么在这里:) – badp 2010-10-16 15:34:41
@Jon - 这是不正确的。 '$(selector).first()'* does *返回一个jQuery对象。你不应该用'$($(selector).first())'来包装它。当我们传递一个数字时,返回一个纯DOM元素的唯一jQuery方法是'.get(0)'。没有数字参数,你会得到一个DOM元素数组。 – user113716 2010-10-16 16:20:29