0

While implementing an internal EventEmitter for a project I was working on, I came across a strange quirk when using Array.prototype.splice inside a for... in loop. The function does not successfully remove the indeces from the array within the loop:

var array = [1, 2, 3, 4, 5], index;

for (index in array) {
    if (index === 2) {
        array.splice(index, 1);
    }

    console.log(array[index]);
}

console.log(array);

Running on Google Chrome version 43, this outputs

1
2
3
4
5
[1, 2, 3, 4, 5]

when I'm expecting something like

1
2
4
5
undefined†
[1, 2, 4, 5]

Is this by design or a bug? I cannot find any documented reference to this behavior.

Possibly, if length is not calculated during each iteration of for... in implementation

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • fyi: for-in with arrays is frowned upon. http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such-a-bad-idea – james emanon Jun 28 '15 at 04:21
  • @jamesemanon thanks for the observation. My question wasn't implying that I thought it was acceptable, but with the body of the loop written the way I have it, my `Array.prototype.slice` worked within a `for(;;)` loop, but not within a `for... in` loop. – Patrick Roberts Jun 28 '15 at 04:24

1 Answers1

1

Great question. :)

In Javascript, Arrays are Objects, which means that Array indices are Object keys. And in Javascript, Object keys are strings.

So your condition index === 2 is always going to be false, because the number 2 is not the same as the string '2'.

One solution would be to continue to use the identity operator (recommended by most) and compare index to the string value '2'

index === '2' 

Or, alternatively, you can use the equality operator which will typecast the comparison (although this will likely get you into trouble at some point)...

index == 2 

but works just fine in your case.

sfletche
  • 47,248
  • 30
  • 103
  • 119