24

I have never seen a JavaScript loop such as this for( ; i-- ; ), used in the code:

uid: function (len) {
    var str = '';
    var src = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var src_len = src.length;
    var i = len;

    for (; i--;) {
        str += src.charAt(this.ran_no(0, src_len - 1));
    }

    return str;
}

I understand the behavior, but I would like it if somebody could share some insights about this type of for loop.

Zach Saucier
  • 24,871
  • 12
  • 85
  • 147
Dejan Toteff
  • 2,075
  • 3
  • 21
  • 30
  • 6
    It's exactly the same as `while(i--)` – Bergi Mar 28 '15 at 15:38
  • 3
    `0` is falsy in JavaScript and all expressions in for loop are optional, so even `for (;;) ` is valid. – Chirag Bhatia - chirag64 Mar 28 '15 at 17:48
  • 2
    I think it's worth mentioning that in C, this kind of for loop isn't so unusual, and especially "for(;;)" is a well known idiom that can be read as "forever". (In fact, I believe this used to be very common. Not sure if this is still true.) But in JavaScript this style lacks clarity because it is not common. Therefore it should in general be avoided in code that other people might want to read. Unless you are sure it will only be read by C programmers. –  Mar 28 '15 at 18:04
  • 1
    I don't think a loop like this should ever be used. for(;i--;) is equivalent to while(i--) and the latter makes it more apparent what's going on. When faced with two ways of expressing something you should almost always take the clearer one--and in this case I would if anything expect the while loop to be faster also. – Loren Pechtel Mar 29 '15 at 04:52
  • 1
    @Loren Pechtel While I agree with your assessment about choosing the most readable style, optimizing `for()` versus `while()` for speed is entering into Mordor and should be avoided almost always. That being said, relevant: http://www.javascripter.net/faq/performanceemptyloops.htm – L0j1k Mar 29 '15 at 08:14
  • 1
    @L0j1k I'm not saying it as an optimization, I'm saying there shouldn't be a hit from using the clearer form, thus there's no reason not to use it. – Loren Pechtel Mar 29 '15 at 20:10
  • It's like the ["goes to" operator](http://stackoverflow.com/questions/1642028) in `while (i --> 0) ...`. – David R Tribble Nov 12 '15 at 16:44

6 Answers6

33

This is a syntax of the for-loop construction:

for ([initialization]; [condition]; [final-expression])
     statement

In your case for (; i--;) {:

  • no variables are initialized, because var i = len; inintialized earlier, so it's not needed.
  • condition part will be truthy until i becomes 0 then loop will terminate. i-- is executed on before each iteration, and due to -- operator it will eventually become 0, so it's falsy, and loop will stop.
  • since i is decremented in condition part of the loop, final-expression is not needed too. Another way to put it: since i is not used inside the loop, it does not matter whether we decrement it before each loop iteration or after each loop iteration.

That being said, it's better to avoid writing loops like above, as it's pretty confusing and hard to read. Prefer traditional for-loops notation.

Salman A
  • 262,204
  • 82
  • 430
  • 521
dfsq
  • 191,768
  • 25
  • 236
  • 258
10

From MDN - for - Optional for expressions:

All three expressions in the head of the for loop are optional.

You don't have to specify all three expressions in for loops. For example, for (;;) is a common wa of writing infinite loop.

In your case, while(i--) would have done the same, there is no good reason to write for (; i--;).

I'd also note that for(var i=len;i>=0;i--) is more robust - it protects you from the case len is negative.

Kobi
  • 135,331
  • 41
  • 252
  • 292
  • 1
    But it's worth noting that `for (; i--;)` is not the same as `for(;i!=0; i--)` because in the former case the `i--` is executed the first time you enter the loop whereas in the latter the `i--` is only executed at the end of each iteration. – Wolfgang Bangerth Mar 29 '15 at 03:40
  • @WolfgangBangerth - I'm not sure what you mean, I never mentioned `for(;i!=0; i--)`. Good point though - if the code used `i`, that would make a difference. – Kobi Mar 29 '15 at 05:01
4

This could be rewritten to

uid: function (len) {
    var str = '';
    var src = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var src_len = src.length;
    var i = len;

    while (i >= 0) {
        str += src.charAt(this.ran_no(0, src_len - 1));
        i = i - 1;
    }

    return str;
}

The for statement creates a loop that consists of three optional expressions.

Javascript consider 0 == false that's why in the case you presented the loop will run until the i variable became zero. It will loop as many times as the src string size.

Note: i-- uses the variable value then decrements it. Take a look at the following situation:

for(;i--;) { // i = length in the condition
     // i === length - 1 here. It will not overflow the array
}

for(;i--;) { // i = 1
     // i === 0 here. It will be the last loop
}

for(;i--;) { // i == 0 == false
     // Not executed
}  
Zach Saucier
  • 24,871
  • 12
  • 85
  • 147
nanndoj
  • 6,580
  • 7
  • 30
  • 42
3

There is nothing wrong.

for(`INIT`;`TEST`;`ACTION`)
{
     `WORK`;
}

The INIT (initialization) can be done outside the loop.

var i=0;
for(;i<=100;i++)
//do something

The TEST part yield a result that is either true or false. Now in this case value of i is tested. Until it becomes zero this works.

The ACTION part is generally used to change the loop variable. But you can leave it also or probably add it to the TEST section like it is done here.

Look this examples are going to clear your idea

var i=0;
for( i++; i++; i+=j); //No body

var i=0;
for(;;); //an infinite loop

var i;
for(i=-4;i;i++);//

Even sometimes WORK is placed in ACTION.

Example:

factorial of x

 for(var i=1,ans=1;i<=x;ans=ans*(i++));

Which can be written this way also-


 var ans=1;
for(var i=1;i<=x;i++)
   ans=ans*i;

NOTE: You can write whichever way you want. It doesn't matter as long as you have written the code properly. Get used to this kind of form you will see them a lot.

Though, it is better to write sometimes in compact form , but remember you should keep the readability.

user2736738
  • 30,591
  • 5
  • 42
  • 56
1

That's just for loop. Before the first semicolon the variable used in the loop is usually declared. But in this case the variable, the variable used in the loop is declared earlier:

var i = len;
   ^^^
for (; i--;) {...

So there is no need to redeclare.

After the first semicolon, there is a condition for the loop to run (i.e. i<6, i>3, etc). If condition returns false, or 0, the loop is exited. In this case, the loop will be broken out when i is 0. It happens eventually, because -- after i decrements it, and therefore there is no need for the expression, which is the place after the second semicolon is reserved for.

nicael
  • 18,550
  • 13
  • 57
  • 90
  • 1
    The condition is there. Because it doesn't look like a condition that doesn't mean it's not a condition. – SeinopSys Mar 28 '15 at 11:17
  • @DJD No condition there. What do you mean? – nicael Mar 28 '15 at 11:26
  • `i--` _returns_ the value of `i` and then decrements its value. At the time `i` is `0` the `i--` returns `0` which is _falsy_ and as of that the condition will be evaluated to _false_. ( `for(;i--;)` is equal to `while(i--)` ) – t.niese Mar 28 '15 at 11:42
0

The first parameter of the for loop has already been defined, so the initial comma is there to delimit it's place in the parameter list.

Andy
  • 157
  • 10
  • I used this kind of thing when I had another similar for loop after this where I was using i again but reset it to zero. Just some small optimization, – Andy Mar 28 '15 at 11:27
  • This isn't a very full answer as it doesn't address all the points of the question – Zach Saucier Mar 28 '15 at 13:21
  • I see that all the points of the question have now been addressed. But I can add that the scope of the i is now outside of the loop, so the value can be used if you break out of the loop prematurely after say finding some solution to a search of an array. Inside of the loop, the i is only locally accessible. – Andy Mar 31 '15 at 13:16