12

I am having trouble understanding how this for-loop terminates in JavaScript:

var files = ["A", "B"];
for (var i = 0, f; f = files[i]; i++) {
   console.log(f);
}

When run, it displays A and B on the screen, but why does f=files[2] end the loop? If I run f=files[2] in my console I get the answer "undefined", so what is the rationale behind the fact that this should end the loop?

Bonus question: Why not write the loop instead as the following?

for (var i=0; i < files.length; i++) {
    f = files[i];
    console.log(f);
}

This seems clearer and more maintainable to me, so is there some reason that the first piece of code would be used over the second?

4
  • 1
    bonus answer: because the first snippet saves the whole line of code Commented Apr 10, 2015 at 14:41
  • 10
    I prefer the second for consistency in a case where the array could have some valid falsy value as false, undefined, null or 0. Commented Apr 10, 2015 at 14:46
  • @Igor files[i] could easily be included in the second line instead of f so the extra line isn't needed. thats just the way the op wrote it Commented Apr 10, 2015 at 14:46
  • 1
    …except that the second snippet is missing a var f declaration. Commented Apr 10, 2015 at 15:44

5 Answers 5

22

The loop ends because undefined is a falsey value.

The reason why use one over the other is user preference. You have a preference while someone else preferred the other way. Someone else might want to use a while loop. There is no right way.

Sign up to request clarification or add additional context in comments.

5 Comments

By falsely you dont mean false == undefined ? do you ?
@cafebabe1991 Boolean(undefined) === false. The coercion in == doesn't line up to that, treating undefined as only equal to itself or null.
Thanks for the answer and in particular the link to the falsey values. That has cleared up a lot and helped my understanding!
You should probably also mention that a null, undefined, 0, or any other falsey value in the array will terminate the loop, too.
@toothbrush Which is what is in the linked question about falsey values.
3

You got "undefined" just when you are running the code in the console. Because when run any code in the console, it will return "undefined" if not return any things.

Comments

2

Arrays are numbered starting at zero, so array[] = [0,1,2]. Your code tries to initialize a value to files[2] which is the third place in the array, but your array is only defined as having 2 spaces. So once it sees that it has reached the end of the array, it exits the loop.

As for one of the loops being favored over the others I would assume your second loop would be better, because the first one it is essentially trying to assign a value out of bounds in the array and failing, so it exits. I would say that the second one is safer.

Comments

2

for ( ExpressionNoInopt ; Expressionopt ; Expressionopt ) Statement

The first Expression in the for statement, if present, is checked for false-ishness to exit the loop. undefined is a falsy so this terminates the loop.

As for the bonus question, there are many ways to write that loop. For me, the code you proposed is more readable. Having said that, you can use Array.forEach to iterate arrays in more recent browsers.

Comments

1

Prefer for (var i=0; i < files.length; i++) {}

Consider arr = [0,1,2]

for (var i = 0; i < arr.length; i++) {} would correctly loop over all elements in the array, but for (var i = 0, item; item = arr[i]; i++) {} would not (and would fail to execute completely).

Note that neither construct is good for handling sparse arrays (but then again, you should probably just use and treat it as an object at that point).

Consider using Array.prototype.forEach or for( var item in arr ) {} when having to deal with sparse arrays. Be aware that for( var item in arr ) {} will also return Array.prototype values, and that Array.prototype.forEach is not implemented in every browser.

3 Comments

@SalmanA I removed my comment. However, doesn't one of the ways of looping through an array also return length?
@toothbrush yes, for( var item in arr ) runs the risk of iterating over prototype'd variables. Try a=[1];a[10]=2;Array.prototype.foo="foo";for (var i in a) {console.log(i)}
@toothbrush some browsers did that and that was incorrect. Discussed in detail here: stackoverflow.com/q/500504/87015

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.