Loop iteration should not be skipped after removing an element with Array.prototype.splice()
- SKIPPED_ITERATION_AFTER_SPLICE
- Code Quality
- Medium
- No tags
This rule applies when an element is removed using Array.prototype.splice()
inside a loop and the element right after the removed one is skipped in the next iteration.
Array.prototype.splice()
shifts the remaining elements after removing an element. For example, arr.splice(i, 1)
shifts the element at i + 1
to i
. If i
is a loop counter, the shifted element will be skipped in the next iteration when the counter is incremented to i + 1
.
This problem can be fixed by applying one of the following according to the intention of the element removal:
- If removing all elements satisfying certain criteria was intended, decrement the loop index variable after doing
splice()
to avoid the skipping. See Example 1 below. - If removing only one element was intended, put
break
to terminate the loop once the intended element is removed. See Example 2 below.
Noncompliant Code Example
View with compliant examples side by side// Example 1
function splitParts(str) {
let parts = str.split(' ');
for (let i = 0; i < parts.length; i++) {
// Empty strings may occur if there exist consecutive spaces.
if (parts[i] === '') {
// SKIPPED_ITERATION_AFTER_SPLICE alarm.
// Some empty strings are not removed if 3 or more consecutive spaces existed.
parts.splice(i, 1);
}
}
return parts;
}
// Example 2
function removeItem(arr, id) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].id === id) {
// SKIPPED_ITERATION_AFTER_SPLICE alarm
arr.splice(i, 1);
}
}
}
Compliant Code Example
View with noncompliant examples side by side// Example 1
function splitParts(str) {
let parts = str.split(' ');
for (let i = 0; i < parts.length; i++) {
// Empty strings may occur if there exist consecutive spaces.
if (parts[i] === '') {
parts.splice(i, 1);
i--;
}
}
return parts;
}
// Example 2
function removeItem(arr, id) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].id === id) {
arr.splice(i, 1);
break;
}
}
}
Version
This rule was introduced in DeepScan 1.48.0.