I have constructed a JavaScript for loop with the run condition set to the length of an options Collection. The length of the options Collection is verified at 27 through console.log before the loop.
But when I run the loop it seems to run only 14 times - the loop removes an option each iteration, and when it's done there are 13 options left. Also I'm running console.log after the loop.
Here is a JSFiddle.
And here is my for loop:
(function () {
var industryOptions = document.getElementsByName("industry")[0].options;
console.log(industryOptions.length);
for (var k = 0; k < industryOptions.length; k++) {
industryOptions.remove(0);
}
console.log(industryOptions.length);
})();
NOTE: When I change the condition from industryOptions.length
to 27, it works as intended.
Why is my for loop stopping early after 14 loops instead of the entire industryOptions.length
? Thanks!
I have constructed a JavaScript for loop with the run condition set to the length of an options Collection. The length of the options Collection is verified at 27 through console.log before the loop.
But when I run the loop it seems to run only 14 times - the loop removes an option each iteration, and when it's done there are 13 options left. Also I'm running console.log after the loop.
Here is a JSFiddle.
And here is my for loop:
(function () {
var industryOptions = document.getElementsByName("industry")[0].options;
console.log(industryOptions.length);
for (var k = 0; k < industryOptions.length; k++) {
industryOptions.remove(0);
}
console.log(industryOptions.length);
})();
NOTE: When I change the condition from industryOptions.length
to 27, it works as intended.
Why is my for loop stopping early after 14 loops instead of the entire industryOptions.length
? Thanks!
-
What is the output of
console.log(industryOptions.length);
– Black Commented Dec 21, 2016 at 18:22 - 5 In each iteration industryOptions.length changes because you remove top one – Gurkan İlleez Commented Dec 21, 2016 at 18:22
-
1
Cache
industryOptions.length
, or loop backwards. The list is live and you are changing it. – Alexander O'Mara Commented Dec 21, 2016 at 18:23 - @EdwardBlack console.log shows 27 before the loop, 13 after – stackingjasoncooper Commented Dec 21, 2016 at 18:23
-
1
The condition
k < industryOptions.length;
is checked on each run – Vinay Commented Dec 21, 2016 at 18:24
5 Answers
Reset to default 7industryOptions.remove(0);
You keep changing the length of your array, even though you are adding to a number. You need to use a different algorithm or technique.
One way is to simply repeat until the array is empty:
while (industryOptions.length > 0)
{ industryOptions.remove(0); }
You could count down from the end rather than counting up:
for (var k = industryOptions.length; k > 0 ; k -= 1)
{ industryOptions.remove(0); }
Another technique is to determine the length before your loop starts rather than re-evaluating the length on each iteration:
var loopStop = industryOptions.length;
for (var k = 0; k < loopStop; k += 1)
{ industryOptions.remove(0); }
Or you could avoid doing the work yourself and let the array handle it:
industryOptions.splice(0, industryOptions.length);
See also this existing answer from 2009: How do I empty an array in JavaScript?
When you splice()
on each loop, the array is reindexed and its length decrease while the number loops is fixed(the original array length set in the loop statement). The loop logic is broken.
Try to reverse array loop order. Replace:
for (var k = 0; k < industryOptions.length; k++) {
with:
for(var k = industryOptions.length; k--;) {
(function () {
var industryOptions = document.getElementsByName("industry")[0].options;
console.log(industryOptions.length);
var length = industryOptions.length;
for (var k = 0; k < length; k++) {
industryOptions.remove(0);
}
console.log(industryOptions.length);
})();
In each iteration you check for length of industryOptions so your for loop ends early
As user3087839 pointed out, each time you remove an item, it lowers the length of industryOptions
, causing it to end before you expect it to. To avoid this, use a predefined length to check against, as such:
(function () {
var industryOptions = document.getElementsByName("industry")[0].options;
console.log(industryOptions.length);
var industryOptionsLength = industryOptions.length;
for (var k = 0; k < industryOptionsLength; k++) {
industryOptions.remove(0);
}
console.log(industryOptions.length);
})();
That happens because line industryOptions.remove(0);
is affecting the industryOptions object itself. Being more specific: In every for
iteration you are decreasing by one the length of industryOptions
object (you're removing one element) and then the loop condition is verified (before the next iteration starts) so you are paring against the length of the object that you just modified. In other words, when you use industryOptions.length
the first iteration will check that k < 27
, the second iteration will check that k < 26
, the third iteration will check that k < 25
and so on. At some point k
will be equal to industryOptions.length
and the loop will stop. That point is when k == industryOptions.length == 14