JSHint显示错误:"Functions declared within loops referencing an outer scoped variable may lead to confusi



我有一个页面,上面有很多div,我正在编写一个函数,该函数在所有div上循环,为它们分配一个随机ID,并为每个div附加一些事件侦听器。然而,当我使用JSHint检查代码时,我会遇到上面列出的问题。我已经研究了这个问题的其他线程,但我不完全理解如何在代码中应用这些答案。以下是与此警告相关的部分:


//global variables
var buttons = document.getElementsByClassName("btn");
var firstClick = 1; //set firstClick flag to 1 on load
var buttonIDs = [];
var clickedButtonID = null;
var clickedButtonColour = null;
var clickedButtonTitle = null;
function addListenersToAllBtns() {
//loop over all buttons on page, assign them unique IDs and attach their EventListeners 
for (let i = 0; i < buttons.length; i++) {
let btn_id = guidGenerator();
buttonIDs[i] = btn_id;
buttons[i].setAttribute("id", btn_id);

//add to child node to only have the left side of the button clickable
buttons[i].childNodes[1].addEventListener("click", function () {
//save button information
clickedButtonID = btn_id;
clickedButtonTitle = buttons[i].childNodes[1].childNodes[1].innerHTML;
//button class format is ".btn colour"
clickedButtonColour = buttons[i].getAttribute("class").split(" ")[1]; 

console.log("The ID of the clicked button is: ", clickedButtonID, "n",
'The colour of the clicked button is ', clickedButtonColour);
if (firstClick == 1) {
firstClick = 0;
window.addEventListener("resize", positionHabitCard);
document.addEventListener('DOMContentLoaded', positionHabitCard, false);
}
});
buttons[i].childNodes[1].addEventListener("click", showHabitCard);
}
}

我已经尝试将函数定义从for循环之外获取,如下所示,并将其传递给addEventListener,但随后它无法访问buttons[i],并且btn_id出现问题(表示它未定义)。

function getButtonData() {
//save button information
clickedButtonID = btn_id;
clickedButtonTitle = buttons[i].childNodes[1].childNodes[1].innerHTML;
//button class format is ".btn colour"
clickedButtonColour = buttons[i].getAttribute("class").split(" ")[1]; 

console.log("The ID of the clicked button is: ", clickedButtonID, "n",
'The colour of the clicked button is ', clickedButtonColour);
if (firstClick == 1) {
firstClick = 0;
window.addEventListener("resize", positionHabitCard);
document.addEventListener('DOMContentLoaded', positionHabitCard, false);
}
}

能找一个更有经验的人看看这个并帮我吗?当谈到JS时,我是一个新手,所以请原谅我可能错过的任何明显错误。

事先非常感谢。

这是一个警告,而不是错误。不过,我真的不能说这是一个准确的警告。

首先,它只是真正的"令人困惑的";如果您仍在循环中使用var声明。var声明仅是function和全局范围的局部声明。因此,对于任何循环都不存在var声明。您可以在循环中放置var声明,但这不会创建它的多个变量。相反,行下的任何引用(比如在函数体中)都将引用循环中声明创建的唯一变量。

这可能会令人困惑,因为任何一个引用都可以更新变量。因此,第一次迭代创建的第一个函数可以更改循环中其他所有函数使用的变量。

有了ES6,就有了letconst,它们引入了块范围,也可以在循环中工作。这意味着循环中迭代n次的声明可以创建n变量,并且块中的每个引用将仅应用于该迭代。

您在循环中使用let声明,这样就不会出现真正的问题。但是,如果将let i更改为var i,或将let btn_id更改为var btn_id,则会发现在循环中创建的所有函数都应用了最后一个按钮的逻辑。这是因为每次迭代都会改变ibtn_id(因为所有函数中每个函数只有一个变量)。

最新更新