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.

Remediation

Compare with a relational operator, so any step that passes the bound still terminates the loop.

// Good
for (let i = 1; i < 10; i += 2) {
  process(i);
}

for (let i = 0; i < n; i++) {
  process(i);
  if (shouldSkip(i)) {
    i++;
  }
}

© 2026 Xygeni. All rights reserved