最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does this jQuery return an index of 3? - Stack Overflow

programmeradmin0浏览0评论

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());

According to the documentation for index:

the return value is an integer indicating the position of the first element within the jQuery object relative to its sibling elements.

Emphasis on first element. But the above code returns 3. Based on the documentation shouldn't this code return 0?

You can see it in action here: /

NOTE:

My selector matches two elements: the first and last LI.

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());

According to the documentation for index:

the return value is an integer indicating the position of the first element within the jQuery object relative to its sibling elements.

Emphasis on first element. But the above code returns 3. Based on the documentation shouldn't this code return 0?

You can see it in action here: http://jsfiddle/Zf9Vv/

NOTE:

My selector matches two elements: the first and last LI.

Share Improve this question edited Dec 8, 2011 at 0:25 Abe Miessler asked Dec 8, 2011 at 0:19 Abe MiesslerAbe Miessler 85.2k104 gold badges321 silver badges495 bronze badges 6
  • 2 Hit the nail on the head. You have uncovered a regression. :) – Jon Commented Dec 8, 2011 at 0:34
  • 1 Yay for me!!! You can view the ticket here: bugs.jquery./ticket/10977 – Abe Miessler Commented Dec 8, 2011 at 0:35
  • Based on my findings (see answer), I think the ticket is misleading. This is a regression introduced in 1.6.3 and should be reported as such. There is (of course) nothing in the 1.6.3 release notes indicating that the documented behavior of index() would have changed. – Jon Commented Dec 8, 2011 at 0:41
  • It definitely does not go into the detail that you do, but misleading? My main point was to bring the discrepancy between documentation and functionality to someone's attention. I'm not familiar with the release notes from 1.6.3 and wouldn't be fortable restating your conclusion. Could you possibly add it as a ment to the ticket? – Abe Miessler Commented Dec 8, 2011 at 0:49
  • See my answer for a potential fix. Here's a link to a fiddle containing a modified copy of the jQuery source, which alerts the correct answer: jsfiddle/Zf9Vv/1 – James Allardice Commented Dec 8, 2011 at 0:52
 |  Show 1 more ment

3 Answers 3

Reset to default 5

Edit (see ments) The original answer is incorrect... I'm going to keep it here for now so the ments make sense.

Looking at the jQuery source for index, you can see the following snippet:

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

Compare this to the corresponding (if very different) snippet from an earlier release, 1.6.2. Note the use of 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() );

It seems that in the current version the this.prevAll part causes the problem. If you change it to this.eq(0).prevAll (which replicates what the index documentation states) then you get the correct value returned. So it would appear this is a jQuery bug.

In the 1.6.2 version, inArray is used. That method returns the index of the first argument in the second argument (or -1 if the first argument is not found in the second). As the first argument is this[0] (the first element in the matched set) we get the expected result.

Here's an updated fiddle with the modified jQuery source included. The correct result is alerted.


Original answer (this is incorrect):

Read the quoted part of the docs again carefully (bold highlighting added):

the return value is an integer indicating the position of the first element within the jQuery object relative to its sibling elements.

Just because two of the siblings have been removed from the matched set, it doesn't change the value returned by index. In other words, the matched element (<li>Fourth Item</li>) will always have index 3, relative to its siblings (unless, of course, new siblings are inserted into the DOM before the element in question).

It's probable that you found a discrepancy between actual jQuery functionality and what the docs say.

The docs state

If no argument is passed to the .index() method, the return value is an integer indicating the position of the first element within the jQuery object relative to its sibling elements.`

However, .index() is returning the index of the last element within the jQuery object.

This can be demonstrated (without introducing a potential issue with the :not selector) in your fiddle by console.log( $("li").index() ); // 3

Maybe a bug report on jQuery is needed?

Update:

Confirmed, this is a regression introduced in jQuery 1.6.3. Earlier versions exhibit the expected behavior (return 0).

After investigating, I have reluctantly e to the conclusion that this cannot be anything else other than a bug in jQuery.

Specifically, in this case at least, index() returns the index relative to its siblings of the second element matched (the bare <li>). This is despite the fact that

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

correctly returns the <li class="selected">.

Furthermore, if we change the selector to

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

then index correctly returns 0.

Tests done using jQuery 1.7.1

发布评论

评论列表(0)

  1. 暂无评论