As splice changes the length you either need to move your iterator or iterate downwards.
You should also be using for, not for..in to iterate over an Array
var arr = [{id:0, type:1}, {id:1, type:1}, {id:2, type:2}]; var type = 1, i; // OR // i = arr.length; for (i = arr.length - 1; i >= 0; --i) { // while (i-- > 0) { if (arr[i].type == type) { arr.splice(i, 1); } } arr; // [{"id": 2, "type": 2}]
Other answers suggest using a the filter method of Arrays which is a great alternative option and you may find it cleaner. However, please be aware the result of these two ways are slightly different as this way will modify the original Array reference ("has side effects"), whereas the filter method will create an entirely new instance of Array and leave the original untouched.
You can think of filter like this, which also shows why it's a bit expensive
function filter(arr, test) { var i, arr_out = []; for (i = 0; i < arr.length; ++i) if (i in arr && test(arr[i]) // invoking test each time is expensive arr_out.push(arr[i]); return arr_out; }
splice can be expensive too, however, as you are moving all the indicies around.
The least expensive way to do this without side effects (i.e. original left alone) is to do a mix of the two; a manual for loop which pushes to a new Array with out test written into it, not invoked seperately
// arr as before var arr2 = [], i; for (i = 0; i < arr.length; ++i) if (arr[i].type === type) // doing our test directly, much cheaper arr2.push(arr[i]); arr2; // desired array
For a original modified, easiest option is to use the splice method I wrote at the start of this answer.
The other option is to copy the original, var arr2 = arr.slice(), then empty the original, arr.length = 0;, then do the last loop I showed except with arr and arr2 swapped around to re-populate arr
[{id:0, type:1}, {id:1, type:1}, {id:2, type:2}]instead of{{id:0, type:1}, {id:1, type:1}, {id:2, type:2}}