我当前正在使用JsHint,并且收到警告W083:“不要在循环内创建函数”。我阅读了《JsLint错误说明》中的这篇文章,并了解了为什么不应该这样做,这实质上归结为JavaScript的异步特性以及变量被覆盖的可能性。
但是,我还在此处阅读了其他几篇文章,尽管这是一个虚假的提示,但根据情况并不一定会导致错误。
我特别担心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的每个功能的危险。
为了避免将此问题标记为重复,我确实看到了这样的问题,但是唯一的答案没有做任何详细说明或解释,根据注释,它看起来始终像是XY问题。我更感兴趣为什么这是它的本质是嵌套循环。
在循环外提取并命名此函数真的安全得多吗?如果将循环计数器复制到匿名函数范围内的变量,是否可以消除这种设计的潜在危险?该函数是否在主for循环之外完全异步执行?
+如果您确实有兴趣:此代码用于确定如果启用了某些选项,是否应在页面加载时禁用某些字段。
问题不在each
循环内使用jQuery ,而是反复声明一个函数。这可能会导致一些奇怪的关闭问题(函数在对循环计数器的引用上关闭,该计数器仍会更新并可以更改),并且在不太聪明的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。如果您考虑一下,这是有道理的,但是如果您不密切注意闭包或具有更复杂的回调,则可能是一个细微的错误。
在循环中未声明函数会迫使您显式绑定或传递循环计数器以及其他变量,并防止此类事情意外发生。
在某些更幼稚的实现中,机器实际上还可以在每次循环迭代时为函数创建一个闭合范围,以避免变量在循环内发生任何潜在的奇怪变化。这可能会导致很多不必要的作用域,从而影响性能和内存。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句