I was working with splice
within a nested for loop and I came across a behaviour I could not understand.
var a = [0, 1, 2, 3, 4];
for (b in a) {
After you remove element 1, then "a" looks like:
[0, 2, 3, 4]
The new element 1 is 2. The next iteration of the loop, then "c" is 2, and a[2]
is indeed 3.
You should not use for…in-enumerations to loop arrays.
That said, your problem is that the .splice method modifies your array, removing an item and adjusting indizes after it. Yet, you do not adjust your iteration variable, so it will skip the index - the old index "1" was visited already, next will be "2" not the new "1" again.
To solve this, you can either loop backwards or decrease the iteration counter by the number or removed items. However, when revisiting the index your condition would always be fulfilled, and you are successively removing all second elements from the arrays until there is no second element left - not sure whether this is your goal.
why is index 2 referring to value 3 , whereas it should refer to 2
Because on the previous iteration, you removed an entry via splice
:
if (c==="1")
a.splice(c, 1);
...so everything shifted up (that's what splice
does). Then the next loop continues with c
being "2"
, and the entry (now) at index 2 is 3
.
Re your comment:
ok , I understand that it shifts the index after splicing , but I am calling splice after doing console.log()... so how is it spliced earlier?
Okay, let's step back:
Before the inner loop starts, a
looks like this:
[0, 1, 2, 3, 4]
On the first pass of your inner loop, c
is "0"
and the entry at index 0
is 0
, so your log statement shows "0==0"
. splice
is not called, and a
is not changed, so it still looks like this:
[0, 1, 2, 3, 4]
On the next pass of your inner loop, c
is "1"
, and the entry at index 1
is 1
, so your log statement shows "1==1"
. Then splice
is called, changing a
so it looks like this:
[0, 2, 3, 4]
On the next pass of your inner loop, c
is "2"
, and the entry at index 2
is 3
(not 2
, because a
has changed), so your log statement shows "2==3"
.
Later, when your outer loop runs again, c
is again "1"
at one point, so another entry gets removed and you see the same effect.
What you should do is actually watch the code run live, single-stepping through with the debugger, and watching how a
changes in real time. All modern browsers have capable debuggers built in, you don't have to litter your code with console.log
statements, you can actually watch what happens.
It's not the reason for your problem, but note that for-in
isn't for looping over array indexes, it's for enumerating the property names of an object (which is why your c==="1"
comparison works, property names are always strings). More: Myths and realities of for..in