为什么这个jQuery返回索引3?

9

HTML:

<ul>
    <li class="selected">First Item</li>
    <li class="disabled">Second Item</li>
    <li class="separator">Third Item</li>
    <li>Fourth Item</li>
</ul>

jQuery:

alert($("li:not(.disabled,.separator)").index());

根据index的文档

返回值是一个整数,表示jQuery对象中第一个元素相对于其兄弟元素的位置。

强调“第一个元素”。但上述代码返回3。根据文档,这个代码不应该返回0吗?

您可以在此处查看其实际效果:http://jsfiddle.net/Zf9Vv/

注意:

我的选择器匹配了两个元素:第一个和最后一个LI


2
你说得对!你发现了一个回归错误 :) - Jon
1
太棒了!你可以在这里查看工单: http://bugs.jquery.com/ticket/10977 - Abe Miessler
根据我的发现(请参见答案),我认为这个问题是误导性的。这是1.6.3引入的一个回归,应该作为这样报告。当然,在1.6.3版本说明中没有任何关于index()文档行为已更改的内容。 - Jon
它绝对不会像你一样深入细节,但误导人吗?我的主要观点是要引起某个人对文档和功能之间的差异的注意。我不熟悉1.6.3版本的发行说明,也不愿意重新陈述你的结论。你能否将它作为评论添加到工单中? - Abe Miessler
请看我的答案,这可能会修复问题。以下是包含修改过的jQuery源代码的fiddle链接,可以弹出正确的答案:http://jsfiddle.net/Zf9Vv/1/ - James Allardice
当然。还要阅读James Allardice的答案,他是第一个解析这个变更集的人。我的观点是,我们可以提供比票据陈述更丰富和可靠的信息,所以让jQuery团队重新发现我们的发现将是一种遗憾。 - Jon
3个回答

5

编辑(请参见评论) 原始答案是不正确的... 我现在会保留它,以便评论有意义。

查看 jQuery 中 index 的源代码,您可以看到以下片段

if ( !elem ) {
    return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
}

将此与早期版本1.6.2中相应(尽管非常不同)的片段进行比较。请注意this[0]的使用:

return jQuery.inArray( this[0],
// If it receives a string, the selector is used
// If it receives nothing, the siblings are used
elem ? jQuery( elem ) : this.parent().children() );

在当前版本中,this.prevAll 部分似乎引起了问题。如果您将其更改为 this.eq(0).prevAll(这复制了 index 文档中所述的内容),那么您将获得正确的返回值。因此,这似乎是一个 jQuery 的错误。
在 1.6.2 版本中,使用了 inArray 方法。该方法返回第一个参数在第二个参数中的索引(或者如果第一个参数未在第二个参数中找到,则返回 -1)。由于第一个参数是 this[0](匹配集合中的第一个元素),因此我们得到了预期的结果。
这里是一个包含修改后的 jQuery 源代码的更新的 fiddle。正确的结果已被提示。

原始答案(这是不正确的):

仔细再次阅读文档中引用的部分(加粗突出显示):

返回值是一个整数,指示jQuery对象中第一个元素相对于其兄弟元素的位置。

即使已从匹配集中删除了两个兄弟元素,它也不会改变index返回的值。换句话说,匹配的元素(<li>Fourth Item</li>)始终相对于其兄弟元素具有索引3(当然,除非在问题元素之前插入新的兄弟元素到DOM中)。


2
但是由于第一个和最后一个LI匹配,它应该选择第一个(索引为0)吗? - Abe Miessler
啊,我明白你的意思了。我会研究一下,所以暂时不会删除我的答案。 - James Allardice
我现在也在看同样的事情,感谢你发布这些信息。 - Jon

4

很可能您发现了实际的jQuery功能与文档所说的不符。

文档中提到:

如果没有向.index()方法传递参数,则返回值是一个整数,表示jQuery对象中第一个元素相对于其兄弟元素的位置。

然而,.index()返回的是jQuery对象中最后一个元素的索引。

可以通过在您的fiddle中使用console.log($("li").index()); // 3来演示这一点(而不引入:not选择器的潜在问题)。

也许需要在jQuery上报告错误?


1
人们,这不是文档问题,这是回归。 - Jon
那是针对我说的吗?我没有说这是一个文档问题,而是实际功能和文档之间存在差异。 - simshaun
它主要是针对群体心理的点赞者,但从某种意义上说,这也适用于您,因为答案给人留下的印象是应该通过更改文档来解决这个问题。 - Jon
看起来这个问题始于1.6.3,当时他们改变了使用.prevAll()计算前一个同级元素的方法。他们需要使用.first().prevAll()代替。https://github.com/jquery/jquery/blob/1.6.3/src/traversing.js#L150-152 - RightSaidFred
这是更改和单元测试的链接(https://github.com/jquery/jquery/commit/9a96af1d59cc6a10b89b6f2489b04871a9c1c7fa#src/traversing.js)。它只针对单个元素进行测试。这是在六月份!...我想我应该先向下滚动一点。这已经被覆盖了!:p - RightSaidFred
显示剩余3条评论

4

更新:

确认,这是jQuery 1.6.3引入的一个回归错误。早期版本表现出了预期的行为(返回0)。

经过调查,我不得不得出结论,这只能是jQuery中的一个bug。

具体来说,在这种情况下,index()返回与其同级的第二个匹配元素(裸露的<li>)的索引。尽管事实上

$("li:not(.disabled,.separator)").get(0)

正确地返回<li class="selected">

此外,如果我们更改选择器为

$("li:not(.disabled,.separator,:last-child)").index()

然后index正确返回0。

使用jQuery 1.7.1进行测试


是的,在测试后,这确实是jQuery中的一个bug。做得好。 - Alex
1
@Alex:我已经测试并确定1.6.3是有问题的版本。现在让我们找出出了什么问题 :) - Jon
@Jon - 看起来出了问题的是从this[0]this的更改(还有许多其他更改-最新版本中的代码完全不同)。请参见我的(更新后的)答案。 - James Allardice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接