JsHint W083不要在循环中使用函数和jQuery的$ .each()函数

时间:2015-05-27 13:51:00

标签: javascript jquery loops

我目前正在使用JsHint并收到警告 W083:“不要在循环中创建函数”。我从JsLint Error Explanations阅读了这篇文章,并理解为什么你不应该这样做,这实际上归结为JavaScript的不正常性以及可能被覆盖的变量。

但是,我还在其他一些帖子中读到了SO虽然这是一个失礼,但并不总是会导致错误。视情况而定。

我特别注意JsHint抱怨的情况是一个使用jQuery $(selector).each()函数的for循环。该函数将函数作为参数。下面是我关注的代码片段。不要担心它实际上做了什么 + ,因为我真的只是以此为例:

for (var i = 0; i < sections.length; i++) {
    disableSectionState[sections[i].name] = {};

    $('.' + sections[i].name).each(function (index, element) {
        var id = $(element).attr('id');
        disableSectionState[sections[i].name][id] = $(element).attr('disabled');
    });

    if (sections[i].isChecked) {
        $('.' + sections[i].name).attr('disabled', 'disabled');
    }
}

本质上,这只是一个for循环中的嵌套for-each循环,所以我不认为这会太危险,但我显然不熟悉js中的所有怪癖。 截至目前,一切都在使用此功能正常工作,但我想在循环中使用jQuery的每个函数向社区询问这种危险。

为了防止将其标记为欺骗,我确实看到了this这样的问题,但唯一的答案并没有详细说明或解释任何内容,并且根据评论,它看起来像是一个XY问题。我对为什么更感兴趣,因为它的核心是它本质上是一个嵌套循环。

在循环之外提取和命名此函数真的更安全吗?如果我将循环计数器复制到匿名函数范围内的变量,是否会消除此设计的潜在危险?该函数是否在主for循环之外完全异步执行?

+ 如果您真正感兴趣:此代码用于确定在启用某些选项时是否应在页面加载时禁用某些字段。

2 个答案:

答案 0 :(得分:11)

问题不是在循环中使用jQuery的each,而是反复声明一个函数。这可能导致一些奇怪的闭包问题(该函数在对循环计数器的引用上关闭,它仍然会更新并且可以更改)并且对于不太聪明的VM来说可能是一个非常重要的性能问题。

所有JSHint都要求你改变是:

function doStuff(index, element) {
  var id = $(element).attr('id');
   disableSectionState[sections[i].name][id] = $(element).attr('disabled');
}

for (var i = 0; i < sections.length; i++) {
  disableSectionState[sections[i].name] = {};

  $('.' + sections[i].name).each(doStuff);

  if (sections[i].isChecked) {
    $('.' + sections[i].name).attr('disabled', 'disabled');
  }
}

当您从循环内异步调用某些内容并关闭循环计数器时,会出现大多数危险。举个例子:

for (var i = 0; i < urls.length; ++i) {
  $.ajax(urls[i], {success: function () {
    console.log(urls[i]);
  });
}

您可能会认为它会在请求成功时记录每个URL,但由于i可能在任何请求从服务器返回之前达到length,因此您更有可能看到最后一个URL反复。如果你考虑它会有意义,但如果你没有密切注意关闭或者有更复杂的回调,它可能是一个微妙的错误。

在循环中不声明函数会强制您显式绑定或传递循环计数器,以及其他变量,并防止这种事情意外地出现。

在一些更天真的实现中,机器实际上也可以在循环的每次迭代中为函数创建闭包范围,以避免在循环内变化的任何潜在的奇怪现象。这可能会导致许多不必要的范围,这会影响性能和内存。

答案 1 :(得分:1)

JSHint是一个非常基于意见的语法检查器。这有点像决定在纸质MLA或APA上做哪种类型的引用。如果你选择一个,你只需遵守他们的规则,因为大多数情况下,它是&#34;对&#34;,但它很少出错。 JSHint还说要始终使用===,但可能会出现使用==的情况。

您可以遵循规则或使用以下

忽略它们
// Code here will be linted with JSHint.
/* jshint ignore:start */
// Code here will be ignored by JSHint.
/* jshint ignore:end */

如果您打算使用JSHint,我会遵守。它倾向于使代码更加一致,当你开始尝试解决一个警告或错误时,它往往会开始创建更多的

  

在循环之外提取和命名此函数真的更安全吗?

  • 在实践中,是的。一般情况下,可能不是。
  

如果我将循环计数器复制到匿名函数范围内的变量,是否会消除此设计的潜在危险?

  • 没有
  

该函数是否在主for循环之外完全异步执行?

  • 非常确定。