为什么 If 语句被视为此循环中的函数?

Why is an If statement considered a function in this loop?

我一直在构建一个经常使用迭代的 React 应用程序。我正在使用 JSLint 并收到烦人的警告:

Don't make functions within a loop

在以下循环中:

if(currentSearch[i].users.length > 0) {
    var matched = false;

    //I hate how JSLint just can't handle setting a variable to true within a function
    //this is loop where I get the warning 
    currentSearch[i].users.some(childUser => {
        if(childUser.id === user.id) {
            return matched = true;
        }
    })
    //^^^^^ Warning

    if(!matched) {
        var alert = new AlertObject(user,currentSearch[i],true,false);
        alerts.push(alert);
    }
}

我不认为我在循环中设置了一个函数?我正在使用 array.some 函数,如果我 return 为真,它会中断循环,这就是我所做的。我 return 一个变量,在循环外声明为真。这让我脱离了循环,并允许我在下面做逻辑。

我还应该指出,这也完全在一个循环中,因为我们正在迭代当前的搜索用户。我没有运行时或编译错误,这段代码工作正常,但也许我将来会为灾难做好准备。

知道我为什么会收到此错误吗?如果我遗漏了一些最佳实践?

我不熟悉 React,但这看起来像一个 ES6 箭头函数:

childUser => { ... }

相当于

function (childUser) { ... }

由于您在第一行中引用了 currentSearch[i],因为 [i] 我假设您在此处粘贴的整个代码块都在某种循环中,可能是 for

然后,您正在为触发错误的 Array.some 回调创建一个函数。

一种解决方案是将该回调声明移至父循环之外,但由于您使用的是作用域中的变量,因此需要进行一些重构。


可能的解决方案

您可以在父循环(您在此处提供的代码之外的循环)之外声明一个函数来检查子用户。

//Please provide a better name for the function according to the context.
const checkChildUser = function (childUser) {
    return this.id === childUser.id;
};

然后传递给你正在使用的Array.some函数:

currentSearch[i].users.some(checkChildUser, user);

好吧,您在 .some() 中提供了一个函数作为参数,这就是触发警告的原因。

ESLint 发出警告的原因

Writing functions within loops tends to result in errors due to the way the function creates a closure around the loop - source

你可以这样做

function compareId(childUser) {
  if (childUser.id === user.id) {
    return true;
  }
}

if (currentSearch[i].users.length > 0) {
  var matched = currentSearch[i].users.some(compareId);

  if (!matched) {
    var alert = new AlertObject(user, currentSearch[i], true, false);
    alerts.push(alert);
  }
}

在您的代码段中,Don't make functions within a loop 警告不是由 if statement 引起的,而是由以下匿名函数引起的:

childUser => {
 if(childUser.id === user.id) {
  return matched = true;
 }
}

既然您说过整个代码都在一个循环中,那么每次迭代都会创建该匿名函数的一个新实例。这会影响性能。

这里的问题是您创建了一个修改 matched 变量的函数。这个变量是用 var 声明的,所以它的作用域是整个函数,而不是单个循环迭代。这可能会导致令人惊讶的结果,因为在每次迭代中创建的函数实际上将引用 相同的 变量。

只需使用 some() 返回的值而不是在回调中更改 matched(如 Yury Tarabanko 所建议的那样)应该会删除警告。