For loop instead of while loop
Solution 1:
I vote for someone having an affinity for bad coding style. That's the only explanation I can see for both the for
loop and the i++
being placed inside of an array subscript. I think this would be better:
while (i < length && callback.apply(object[i], args)) {
i++;
}
Or if you happen to feel that the ===
operator in the original example has value, then:
while (i < length && callback.apply(object[i], args) !== false) {
i++;
}
Another possible reason for doing this may have been as a performance optimization. Although this quick benchmark that I put together seems to disprove that theory. On Windows the while
loop above is 20% faster than the original for
loop in Chrome, in IE and Firefox both loops perform the same. On OS X the for
loop has a 10% advantage in Firefox, there is no difference between the two in Chrome, and Safari prefers the while
loop by 6%.
So from a performance standpoint it's a wash. If anything then judging by market share you would probably want to optimize for Chrome on Windows before optimizing for Firefox on Mac, in which case the while
loop would be preferred.
Which says to me that it's unlikely that performance optimization played a factor with this code. And I return to my original theory that it's just an example of poor coding style making it past the code-review process.
Solution 2:
Probably because it was "refactored" from a for (x in obj)
loop: http://james.padolsey.com/jquery/#v=1.3.2&fn=jQuery.each
Solution 3:
Here is the commit that introduced this oddity.
Commit message:
jquery core: code reduction at
$.each
and$.curCSS
.
Snip from the diff:
- for ( var i = 0, length = object.length; i < length; i++ )
- if ( callback.apply( object[ i ], args ) === false )
+ for ( ; i < length; )
+ if ( callback.apply( object[ i++ ], args ) === false )
It would appear that the author simply missed the opportunity to change the for
into a while
.
Solution 4:
First, there is never a length cost for using a for
loop over a while
loop, but you get additional functionality with the for
loop, so some coders just always use the for
:
for(;<condition>;){}
while(<condition>){}
That said, I think the purpose here may be for consistency with the surrounding code.
For example, here is part of the original code. As you can see, in this code you can stay in the "for" loop mode of thinking the whole time, so it feels more consistent:
if (args) {
if (isObj) {
for (name in object) {
if (callback.apply(object[name], args) === false) {
break;
}
}
} else {
for (; i < length;) {
if (callback.apply(object[i++], args) === false) {
break;
}
}
}
}
Compare this to replacing the second loop with a while
. When you read this code, you have to switch from the "for" loop mode of thinking to the "while" loop mode of thinking. Now I don't know about you, but I find it slightly faster for my eyes to switch between the loop conditions above as opposed to the loop conditions below. This is because in the above case I can just concentrate on the conditions, whereas in the below case my eyes are drawn to reread the while
and the for
each time because they are different:
if (args) {
if (isObj) {
for (name in object) {
if (callback.apply(object[name], args) === false) {
break;
}
}
} else {
while (i < length) {
if (callback.apply(object[i++], args) === false) {
break;
}
}
}
}
Solution 5:
I've found that things like this occur when I rewrite things or if multiple people touch a piece of code. Can't see any particular reason for it.
I hope i gets initialized properly above this block.