【问题标题】:Why is an If statement considered a function in this loop?为什么 If 语句在此循环中被视为函数?
【发布时间】:2018-10-19 16:30:41
【问题描述】:

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

不要在循环中创建函数

在以下循环中:

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 函数,如果我返回 true,它将打破循环,这就是我所做的。我返回一个在循环外声明的变量为真。这让我脱离了循环,并允许我在下面做逻辑。

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

任何想法为什么我会收到此错误?如果我遗漏了一些最佳实践?

【问题讨论】:

  • 使用some 的方式多么奇怪:)。您不需要在回调之外改变变量。只需使用返回的值const matched = currentSearch[i].users.some(childUser => childUser.id === user.id)

标签: javascript reactjs jslint


【解决方案1】:

由于在第一行中您引用了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);

【讨论】:

  • 理想情况下,我希望将变量保留在它们所在的范围内,以免让可能想要阅读我的代码的人复杂化。如果我保持原样并忽略错误,这会被认为是不好的做法吗?
  • @bflynnigan 我编辑了我的答案,提供了一种解决问题的方法。让我知道它是否适合您。
  • 是的,这确实有效,但奇怪的是,当我在构建 408 个警报对象之前运行代码时,但是当我使用你的代码运行时,我得到 411。Sooooo 我将进行更多调查,谢谢你的帮助!
【解决方案2】:

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

childUser => { ... }

相当于

function (childUser) { ... }

【讨论】:

  • 但是使用 Array.Some() 您将函数作为参数传递给它:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 另外,当我将函数作为参数传递给其他 100 个或所以有时我打电话给array.Some
  • 我的猜测是 JSLint 不够聪明,无法知道这是 React 的常规做法。您可以做一些配置来阻止它抱怨吗?
  • 是的,有:/*jshint loopfunc: true*/ 虽然这实际上对我不起作用,但我想知道为什么它会在这里而不是其他地方抛出错误
  • 小心,是的,它是一个箭头函数,但它与声明一个函数不一样。检查这个medium.com/@thejasonfile/…
  • 警告是关于效率的。在循环之外声明一次函数更有效,而不是在循环内部每次迭代都会创建它并减慢速度并可能使用更多内存。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

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

    由于您已经说过整个代码都在一个循环中,因此每次迭代都会创建该匿名函数的一个新实例。这会影响性能。

    【讨论】:

      【解决方案5】:

      好吧,您在 .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);
        }
      }
      

      【讨论】:

      • 不应该是:varmatched = currentSearch[i].users.some(compareId);
      猜你喜欢
      • 2011-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      • 2016-10-29
      • 2017-01-27
      • 1970-01-01
      相关资源
      最近更新 更多