Reputation: 776
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
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
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