Skip to main content
Harbs.
Legend
June 6, 2010
Question

While Loop with Array.pop() Gotcha

  • June 6, 2010
  • 1 reply
  • 13924 views

Just a bit of a heads up:

A number of us have been using a while(obj=array.pop()){} construct for a while. (I believe Marc was the one to introduce this construct to this forum.)

While this is considerably more efficient than a standard for loop when you don't need the array when the loop ois done, there's a not-so-obvious gotcha:

0 in javascript is evaluated to false, so : while(0) is equivalent to while(false).

If you have an loop like this:

ar = [1,0,8,6];
while(a=ar.pop()){
    // do your stuff
    }

6 and 8 will resolve true, but 0 will not. The loop will exit when it hits 0, and neither 0 nor 1 will be processed.

This loop is no good either:

ar = [1,0,8,6];
while(a=ar.pop() != null){
    //do your stuff
    }

because "a" will evaluate to either true or false instead of the value of the array because statements are processed backwards (i.e. a = (ar.pop != null)).

Instead you need (note the extra parenthesis):

ar = [1,0,8,6];
while((a=ar.pop()) != null){
    //do your stuff
    }

HTH,

Harbs

This topic has been closed for replies.

1 reply

Harbs.
Harbs.Author
Legend
June 6, 2010

Actually, even the last construct is not  safe. If there's a null object in the array it'll exit prematurely as well.

For null objects, this will work:

ar = [1,null,8,6];
while((a=ar.pop()) !== undefined){
    //do your stuff
}

But if you have a non-consecutive array this too will fall flat on its face:

ar = [1,null,8,6];
ar[6] = 2;
while((a=ar.pop()) !== undefined){
    //this will only process 2
}

Bottom line, don't use the pop() as the condition of the loop. Do something like this instead:

ar = [1,null,8,6];

ar[6] = 2;
while(ar.length){
    a=ar.pop();
    // now we can process all elements of the array!
}

Harbs

Marc Autret
Legend
June 7, 2010

Good point, Harbs ;-)

That's why I wouldn't recommand using the while( a=ar.pop() ){...} pattern on simple one-dimensional arrays that contain, or could contain primitive types. As a general rule I use this tip on temporary arrays of objects, or on n-dimensional temporary arrays, because I am absolutely sure that none of the elements can be evaluated to false. Then it is a useful shortcut. In other situations the old good index loop is the best although it requires an additional variable.

@+

Marc

Harbs.
Harbs.Author
Legend
June 7, 2010

Hi Marc,

I wasn't blaming you for my mistakes! I just got bitten by using this technique for primitive type arrays, and I figured I should prevent others from making my mistake...

But even for primitive arrays, while(array.length)array.pop() is more efficient than a for loop.

Harbs