Equality Comparison In Loop Condition
ID |
javascript.equality_in_loop_condition |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Code Smell |
Language |
JavaScript |
Tags |
reliability, suspicious-comparison |
Description
Reports a classic for loop whose termination condition compares its counter with ==, !=, === or !== while the update clause steps by more than one unit, or while the body also moves the counter.
The safe, idiomatic for (let i = 0; i !== n; i++) is not reported: a step of exactly one unit can never skip past an integer boundary, so !== behaves identically to a relational operator there. Also excluded are a comparison against null or undefined, a condition that assigns as part of the test, a header declaring more than one variable, and a counter whose initial value is not a plain number literal — which keeps object and iterator walks out.
Rationale
// Bad
for (let i = 1; i !== 10; i += 2) { // 1, 3, 5, 7, 9, 11, ... never 10
process(i);
}
for (let i = 0; i !== n; i++) {
process(i);
if (shouldSkip(i)) {
i++; // the body can step over n
}
}
-
An equality test only ever holds at one exact value, so a step that overshoots it turns the condition into one that is never true and the loop runs forever.
-
A relational operator tolerates the overshoot: the loop stops on the first iteration past the bound whatever the step size is.
-
The failure depends on the arithmetic rather than on the shape of the code, so it hides until the bound or the step changes — often long after the loop was written.