版本

no-unreachable-loop

禁止迴圈主體只允許一次迭代

永遠無法達到第二次迭代的迴圈可能是程式碼中的錯誤。

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 迴圈。避免在這種情況下使用迴圈結構被認為是一種最佳實踐。

規則詳情

此規則旨在透過對迴圈主體執行靜態程式碼路徑分析,來偵測和禁止最多只能執行一次迭代的迴圈。

特別是,此規則將禁止迴圈主體在所有程式碼路徑中都退出迴圈的迴圈。如果迴圈主體中的所有程式碼路徑都將以 breakreturnthrow 陳述式結束,則無論迴圈的條件如何,此類迴圈的第二次迭代肯定無法到達。

此規則會檢查 whiledo-whileforfor-infor-of 迴圈。您可以選擇停用對這些結構的檢查。

此規則的不正確程式碼範例

在線上練習場開啟
/*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;
}

此規則的正確程式碼範例

在線上練習場開啟
/*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;
    }
}

請注意,此規則並非設計用於檢查迴圈條件,因此在以下範例等情況下不會發出警告。

此規則其他正確程式碼範例

在線上練習場開啟
/*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);
}

選項

此規則有一個物件選項,其中一個選項為

  • "ignore" - 此規則將忽略的迴圈類型可選陣列。

忽略

您可以在 "ignore" 陣列中指定最多 5 個不同的元素

  • "WhileStatement" - 忽略所有 while 迴圈。
  • "DoWhileStatement" - 忽略所有 do-while 迴圈。
  • "ForStatement" - 忽略所有 for 迴圈(不適用於 for-infor-of 迴圈)。
  • "ForInStatement" - 忽略所有 for-in 迴圈。
  • "ForOfStatement" - 忽略所有 for-of 迴圈。

此規則使用 "ignore" 選項的正確程式碼範例

在線上練習場開啟
/*eslint no-unreachable-loop: ["error", { "ignore": ["ForInStatement", "ForOfStatement"] }]*/

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

for (const a of b) break;

已知限制

一般而言,靜態程式碼路徑分析不會評估條件。由於此事實,此規則可能會遺漏回報以下情況

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

版本

此規則於 ESLint v7.3.0 中引入。

資源

變更語言