no-loop-func

禁止在循环语句中包含不安全引用的函数声明

由于函数在循环周围创建闭包的方式,在循环中编写函数往往会导致错误。例如:

¥Writing functions within loops tends to result in errors due to the way the function creates a closure around the loop. For example:

for (var i = 0; i < 10; i++) {
    funcs[i] = function() {
        return i;
    };
}

在这种情况下,你会期望在循环中创建的每个函数都返回不同的数字。实际上,每个函数都返回 10,因为这是作用域中 i 的最后一个值。

¥In this case, you would expect each function created within the loop to return a different number. In reality, each function returns 10, because that was the last value of i in the scope.

letconst 缓解了这个问题。

¥let or const mitigate this problem.

for (let i = 0; i < 10; i++) {
    funcs[i] = function() {
        return i;
    };
}

在这种情况下,循环中创建的每个函数都按预期返回不同的数字。

¥In this case, each function created within the loop returns a different number as expected.

规则详情

¥Rule Details

引发此错误是为了高亮一段可能无法按预期工作的代码,并且还可能表明对该语言的工作方式存在误解。如果你不修复此错误,你的代码可能会毫无问题地运行,但在某些情况下,它可能会出现意外行为。

¥This error is raised to highlight a piece of code that may not work as you expect it to and could also indicate a misunderstanding of how the language works. Your code may run without any problems if you do not fix this error, but in some situations it could behave unexpectedly.

此规则不允许循环中包含不安全引用的任何函数(例如,从外部范围修改变量)。此规则忽略 IIFE,但不忽略异步或生成器函数。

¥This rule disallows any function within a loop that contains unsafe references (e.g. to modified variables from the outer scope). This rule ignores IIFEs but not async or generator functions.

此规则的错误代码示例:

¥Examples of incorrect code for this rule:

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

var i = 0;
while(i < 5) {
    var a = function() { return i; };
    a();

    i++;
}

var i = 0;
do {
    function a() { return i; };
    a();

    i++
} while (i < 5);

let foo = 0;
for (let i = 0; i < 10; ++i) {
    //Bad, `foo` is not in the loop-block's scope and `foo` is modified in/after the loop
    setTimeout(() => console.log(foo));
    foo += 1;
}

for (let i = 0; i < 10; ++i) {
    //Bad, `foo` is not in the loop-block's scope and `foo` is modified in/after the loop
    setTimeout(() => console.log(foo));
}
foo = 100;

var arr = [];

for (var i = 0; i < 5; i++) {
    arr.push((f => f)(() => i));
}

for (var i = 0; i < 5; i++) {
    arr.push((() => {
        return () => i;
    })());
}

for (var i = 0; i < 5; i++) {
    (function fun () {
        if (arr.includes(fun)) return i;
        else arr.push(fun);
    })();
}

此规则的正确代码示例:

¥Examples of correct code for this rule:

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

var a = function() {};

for (var i=10; i; i--) {
    a();
}

for (var i=10; i; i--) {
    var a = function() {}; // OK, no references to variables in the outer scopes.
    a();
}

for (let i=10; i; i--) {
    var a = function() { return i; }; // OK, all references are referring to block scoped variables in the loop.
    a();
}

var foo = 100;
for (let i=10; i; i--) {
    var a = function() { return foo; }; // OK, all references are referring to never modified variables.
    a();
}
//... no modifications of foo after this loop ...

var arr = [];

for (var i=10; i; i--) {
    (function() { return i; })();
}

for (var i = 0; i < 5; i++) {
    arr.push((f => f)((() => i)()));
}

for (var i = 0; i < 5; i++) {
    arr.push((() => {
        return (() => i)();
    })());
}

版本

此规则是在 ESLint v0.0.9 中引入。

资源

ESLint 中文网
粤ICP备13048890号