no-unreachable-loop

不允许循环体只允许一次迭代

永远无法到达第二次迭代的循环可能是代码中的错误。

¥A loop that can never reach the second iteration is a possible error in the code.

for (let i = 0; i < arr.length; i++) {
    if (arr[i].name === myName) {
        doSomething(arr[i]);
        // break was supposed to be here
    }
    break;
}

在只有一次迭代(或最多一次迭代)是预期行为的极少数情况下,应重构代码以使用 if 条件而不是 whiledo-whilefor 循环。在这种情况下避免使用循环构造被认为是最佳实践。

¥In rare cases where only one iteration (or at most one iteration) is intended behavior, the code should be refactored to use if conditionals instead of while, do-while and for loops. It’s considered a best practice to avoid using loop constructs for such cases.

规则详情

¥Rule Details

此规则旨在通过对循环体执行静态代码路径分析来检测和禁止最多可以进行一次迭代的循环。

¥This rule aims to detect and disallow loops that can have at most one iteration, by performing static code path analysis on loop bodies.

特别是,该规则将禁止循环体的主体在所有代码路径中都退出循环。如果循环体中的所有代码路径都以 breakreturnthrow 语句结尾,那么无论循环的条件如何,这种循环的第二次迭代肯定是无法到达的。

¥In particular, this rule will disallow a loop with a body that exits the loop in all code paths. If all code paths in the loop’s body will end with either a break, return or a throw statement, the second iteration of such loop is certainly unreachable, regardless of the loop’s condition.

此规则检查 whiledo-whileforfor-infor-of 循环。你可以选择禁用对这些构造中的每一个的检查。

¥This rule checks while, do-while, for, for-in and for-of loops. You can optionally disable checks for each of these constructs.

此规则的错误代码示例:

¥Examples of incorrect code for this rule:

在线运行
/*eslint no-unreachable-loop: "error"*/

while (foo) {
    doSomething(foo);
    foo = foo.parent;
    break;
}

function verifyList(head) {
    let item = head;
    do {
        if (verify(item)) {
            return true;
        } else {
            return false;
        }
    } while (item);
}

function findSomething(arr) {
    for (var i = 0; i < arr.length; i++) {
        if (isSomething(arr[i])) {
            return arr[i];
        } else {
            throw new Error("Doesn't exist.");
        }
    }
}

for (key in obj) {
    if (key.startsWith("_")) {
        break;
    }
    firstKey = key;
    firstValue = obj[key];
    break;
}

for (foo of bar) {
    if (foo.id === id) {
        doSomething(foo);
    }
    break;
}

此规则的正确代码示例:

¥Examples of correct code for this rule:

在线运行
/*eslint no-unreachable-loop: "error"*/

while (foo) {
    doSomething(foo);
    foo = foo.parent;
}

function verifyList(head) {
    let item = head;
    do {
        if (verify(item)) {
            item = item.next;
        } else {
            return false;
        }
    } while (item);

    return true;
}

function findSomething(arr) {
    for (var i = 0; i < arr.length; i++) {
        if (isSomething(arr[i])) {
            return arr[i];
        }
    }
    throw new Error("Doesn't exist.");
}

for (key in obj) {
    if (key.startsWith("_")) {
        continue;
    }
    firstKey = key;
    firstValue = obj[key];
    break;
}

for (foo of bar) {
    if (foo.id === id) {
        doSomething(foo);
        break;
    }
}

请注意,此规则并非旨在检查循环条件,并且不会在以下示例中触发警告。

¥Please note that this rule is not designed to check loop conditions, and will not warn in cases such as the following examples.

此规则的附加正确代码示例:

¥Examples of additional correct code for this rule:

在线运行
/*eslint no-unreachable-loop: "error"*/

do {
    doSomething();
} while (false)

for (let i = 0; i < 1; i++) {
    doSomething(i);
}

for (const a of [1]) {
    doSomething(a);
}

选项

¥Options

此规则有一个对象选项,有一个选项:

¥This rule has an object option, with one option:

  • "ignore" - 此规则将忽略的循环类型的可选数组。

    ¥"ignore" - an optional array of loop types that will be ignored by this rule.

ignore

你可以在 "ignore" 数组中指定最多 5 个不同的元素:

¥You can specify up to 5 different elements in the "ignore" array:

  • "WhileStatement" - 忽略所有 while 循环。

    ¥"WhileStatement" - to ignore all while loops.

  • "DoWhileStatement" - 忽略所有 do-while 循环。

    ¥"DoWhileStatement" - to ignore all do-while loops.

  • "ForStatement" - 忽略所有 for 循环(不适用于 for-infor-of 循环)。

    ¥"ForStatement" - to ignore all for loops (does not apply to for-in and for-of loops).

  • "ForInStatement" - 忽略所有 for-in 循环。

    ¥"ForInStatement" - to ignore all for-in loops.

  • "ForOfStatement" - 忽略所有 for-of 循环。

    ¥"ForOfStatement" - to ignore all for-of loops.

使用 "ignore" 选项的此规则的正确代码示例:

¥Examples of correct code for this rule with the "ignore" option:

在线运行
/*eslint no-unreachable-loop: ["error", { "ignore": ["ForInStatement", "ForOfStatement"] }]*/

for (var key in obj) {
  hasEnumerableProperties = true;
  break;
}

for (const a of b) break;

已知限制

¥Known Limitations

静态代码路径分析通常不评估条件。由于这一事实,此规则可能会遗漏报告案例,例如:

¥Static code path analysis, in general, does not evaluate conditions. Due to this fact, this rule might miss reporting cases such as the following:

for (let i = 0; i < 10; i++) {
    doSomething(i);
    if (true) {
        break;
    }
}

版本

此规则是在 ESLint v7.3.0 中引入。

资源

ESLint 中文网
粤ICP备13048890号