Why does the splice method have this strange behavior?

In my application I need to delete an element from an array. However I am new to JS. I searched the web and every blog post was talking about splice() method. So I considered to used it, but it has a very strange behavior.

Here the post I found : http://www.w3schools.com/jsref/jsref_splice.asp http://viralpatel.net/blogs/javascript-array-remove-element-js-array-delete-element/

Here is my Test:

it("should delete all elements in array", function () {
    var ary = new Array();

    for (i = 0; i < 10; i++) {
        ary[i] = Math.random();
    }

    expect(ary.length).toBe(10);

    for (i = 0; i < 10; i++) {
        ary.splice(i, 1);
    }

    expect(ary.length).toBe(0);

});

And here is the result of the test:

  Firefox 15.0.1 Linux: Run 7 tests (Passed: 6; Fails: 1; Errors 0) (44.00 ms)
    should delete all elements in array failed (5.00 ms): Error: Expected 5 to be 0.

I use angular JS.

Thanks very much for replies. Here is another test that just don't pass:

var ary = new Array();

        ary = ['a', 'b', 'c', 'd'];

        ary.splice(0, 1);

        ary.splice(1, 1);

        ary.splice(2, 1);

        ary.splice(3, 1);

        expect(ary.length).toBe(0);

Firefox 15.0.1 Linux: Run 7 tests (Passed: 6; Fails: 1; Errors 0) (49.00 ms)
    Posting server policy.should delete all elements in array failed (5.00 ms): Error: Expected 2 to be 0.

as @Matteo Tassinari suggest this should one should delete all elements right ??

The reason is simple: with each new splice your array will become shorter:

var arr = [1, 2, 3];
arr.splice(0, 1);
console.log(arr[0]); // 2
console.log(arr[2]); // undefined
console.log(arr.length); // 2

In the second loop of your code splice will change your array only five times. But the sixth time (when i will be equal to 5), arr.splice(5, 1) operation will effectively result in no-op, as your array will be already of 5 elements only.

You can fix it as in @MatteoTassinari answer, or just use splice(0, 1) (or just shift()) instead of splice(i, 1).

Try replacing this:

for (i = 0; i < 10; i++) {
    ary.splice(i, 1);
}

with this:

for (i = 0; i < 10; i++) {
    ary.splice(0, 1);
}

To delete a specific element, given for example:

ary = ['a', 'b', 'c', 'd'];

if you want to delete the 'c' simply do:

ary.splice(2, 1);

In fact 2 here is the 0-based index of the element which has to be deleted.

For that to work, you'd need to always remove the element at index 0. Otherwise, after, say, 8 elements, you'd be doing ary.splice(8, 1), and given that at this point, the array only has 2 elements left, arr.splice(8, 1) won't remove any, since the index 8 no longer exists.

for (i = 0; i < 10; i++) {
    ary.splice(0, 1);
}

As you splice elements from the array, the array becomes shorter. As a result, the last 5 iterations of your loop attempt to splice elements that do not exist.

If you change the code to this:

for (i = 0; i < 10; i++) {
    ary.splice(0, 1);
}

It would work as expected by your unit test.

When you splice your array, (and remove one array element), you also "move" all the other array elements forward.

Consider this array before any splicing:

ary = [0,1,2,3,4,5,6,7,8,9]

After ary.splice(0,1), it looks like this:

ary = [1,2,3,4,5,6,7,8,9],

Notice, that the 0th index (ary[0]) is now 1, and when you proceed to do a ary.splice(1, 1), then you don't remove the first element, but actually removes the second element (being 2 in this case)

I know this is not what you're asking for, but a more efficient way to "reset" your array is to do one of these two things:

ary.length = 0;
// or:
ary = [];