kindisch
kindisch

Reputation: 776

jQuery eq() caused infinite iteration

When I try to sum things up in my code, I figured out when I write something like this:

var $elements = $('div');
for ( var i = 0, $element; $element = $elements.eq(i); i++ ) {
    $element.text( 'Hello' );
}

the loop will never end. I would like to know, why that is happening. Caused it an error if I call functions inside condition or does jQuery just not return accurate data so therefore the loop-condition can't recognize the current index?

Upvotes: 4

Views: 325

Answers (2)

nnnnnn
nnnnnn

Reputation: 150070

The .eq() method always returns a jQuery object. If you specify an index that doesn't exist you get an empty jQuery object. But any object is truthy, so your loop condition is always truthy even after i goes past the last element. So, infinite loop.

You need to test the length:

for ( var i = 0, $element; i < $elements.length && ($element = $elements.eq(i)) ; i++ )

But why not just use the .each() method to loop?

The pattern of assigning the current element as the loop condition does work with an array:

for ( var i = 0, element; element = anArray[i]; i++ ) 

assuming none of the elements have a falsey value, because when i reaches an array.length then anArray[i] will be undefined which is falsey.

Upvotes: 3

Mike Cluck
Mike Cluck

Reputation: 32511

Because $ and, in turn, $elements.eq will always return an object, even if nothing matches the query. That object will have a length of 0 but it will still be an object. Objects are truthy values.

function log(msg) {
  document.querySelector('pre').innerText += msg + '\n';
}

log($('p').eq(0)); // First p element
log($('p').eq(1)); // Second p element
log($('p').eq(2)); // Third p element
log($('p').eq(3)); // No matching p element but look at what we get

if ($('p').eq(9001)) {
  log('Yup, still a truthy value');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>1</p>
<p>2</p>
<p>3</p>

<pre></pre>

Upvotes: 0

Related Questions