2

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!

5 Answers5

7
industryOptions.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?

Community
  • 1
  • 1
dsh
  • 12,037
  • 3
  • 33
  • 51
3

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--;) {
SLePort
  • 15,211
  • 3
  • 34
  • 44
1
(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

Gurkan İlleez
  • 1,503
  • 1
  • 10
  • 12
  • ah, was about to post this. darn. – TrojanByAccident Dec 21 '16 at 18:24
  • Think you should include some info about why this actually occurs rather than just posting fixed code. The reason is an element is being removed from the array in each iteration as well as the counter being incremented. The length is checked on each iteration of the loop and because an element has been removed it is one shorter than it was previously. Caching the original length of the array as you have done in your answer ensures the value remains static and unchanging, regardless of the number of elements that are removed from the original array. – ryansin Dec 21 '16 at 18:30
0

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);
})();
Community
  • 1
  • 1
TrojanByAccident
  • 227
  • 1
  • 6
  • 20
0

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 comparing 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

agurodriguez
  • 480
  • 2
  • 6
  • 19