Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JavaScript循环中添加EventListener而不触发JSHint';这是令人困惑的语义错误吗?_Javascript_Html_Dom_Jshint - Fatal编程技术网

如何在JavaScript循环中添加EventListener而不触发JSHint';这是令人困惑的语义错误吗?

如何在JavaScript循环中添加EventListener而不触发JSHint';这是令人困惑的语义错误吗?,javascript,html,dom,jshint,Javascript,Html,Dom,Jshint,我正在使用DOM在JavaScipt中创建一个动态项目列表。每个项目都有一个链接(一个HTML元素),链接到页面上的另一个元素;允许用户编辑团队的表单。链接工作正常,但我试图通过向链接添加eventListener使表单工作,因为表单需要获得我们正在编辑的团队作为参考 下面是有问题的代码: for (let i = 0; i < teams.length; i++) { let row = table.insertRow(-1); //removed code th

我正在使用DOM在JavaScipt中创建一个动态项目列表。每个项目都有一个链接(一个HTML元素),链接到页面上的另一个元素;允许用户编辑团队的表单。链接工作正常,但我试图通过向链接添加eventListener使表单工作,因为表单需要获得我们正在编辑的团队作为参考

下面是有问题的代码:

    for (let i = 0; i < teams.length; i++) {
    let row = table.insertRow(-1);
    //removed code that made cells under the row
    let link = document.createElement("a");
    link.setAttribute("href","#form");
    link.team = teams[i];
    link.addEventListener("click", function (e) {
        updateForm(link.team);
    });
    link.textContent = teams[i].name;
    //code that adds the link and other elements into the cells of the table
}
如果我理解正确,这是因为变量
table
不在循环范围内。然而,我不明白为什么将表放入循环中会改变任何事情。我到底应该在代码中修改什么来确保JSHint会满意呢?如果添加eventListener似乎是更好的解决方案,我还可以使用其他方法

干杯

如果我理解正确,这是因为变量table存在于循环范围之外

链接
,而不是
表格

我到底应该在代码中修改什么来确保JSHint会满意呢

我从另一个角度来看:您需要在JSHint/您的linting设置中更改什么,以便在回调中使用
link
的完全有效的代码不会触发linting错误?如果您的代码使用的是
var
,则警告将非常有用,但您的代码使用的是
let

IIRC,JSHint比它最初基于的JSLint(几年前现在)更具可配置性,当您使用
let
for
link
时,您可能会查看是否有一个选项可以关闭此特定警告

或者,您可以研究另一种linting解决方案(ESLint非常流行)

但是,您很可能会更改
link
引用的对象的
team
属性。如果您想消除这种可能性并摆脱显式函数,可以使用
bind

link.addEventListener(“单击”,updateForm.bind(null,link.team));
这也将消除JSHint警告

或者,由于您正在元素本身上使用expando属性,因此可以使用
this

link.addEventListener(“单击”,函数(){
updateForm(this.team);
});
…但我建议您不要在DOM元素上使用expando属性。例如:

for (const team of teams) {
    const row = table.insertRow(-1);
    //removed code that made cells under the row
    const link = document.createElement("a");
    link.setAttribute("href","#form");
    link.addEventListener("click", () => { // Or:
        updateForm(team);                  //     link.addEventListener("click", updateForm.bind(null, team));
    });                                    // 
    link.textContent = team.name;
    //code that adds the link and other elements into the cells of the table
}

每当你在循环b/c中定义了一个你没有定义的函数时,Linters总是抱怨。(我有点惊讶JSHint没有,但JSLint似乎也不再认为这是一个错误!)

与linters的旧版本一样,我认为在循环的每次迭代中[重新]定义相同的函数在任何时候都是一种糟糕的做法。因为函数声明发生在一个循环中,所以每个单独函数的逻辑与其他函数的逻辑相同。这意味着代码不能是干的。它还允许像您这样的复杂范围设置

link.addEventListener("click", function (e) {
    updateForm(link.team);
});    
通常,您应该将该函数从循环中拉出,并在循环外定义对它的单个引用

但是…您通过后门将变量传递到函数中,使用了一些,嗯,创造性的闭包,这是一个更细微的错误[林特显然仍然关心]

这里有一种方法可以修复lint,使初始代码中的作用域的重要性变得明确(尽管要继续阅读!)

和繁荣。没有古怪的作用域,没有重复的函数声明。太好了


Expando警告 同样,TJ关于避免“expando properties”的警告是一个非常好的警告。是非标准的,在对象初始化后,您会将其粉碎到DOM元素上

其他库通常可以在没有警告的情况下编辑和/或删除这些属性。你最好使用

。。。或者,我的偏好是,拥有一个查找表,可以通过向每个
链接添加唯一的元素ID来访问该表

也就是说,我不喜欢TJ的解决方案,即保持您最初的范围依赖性时髦^D、 但它也能起作用


有意义吗?

您使用的是最新版本的JSLint吗?对于它来说,抱怨你问题中的代码是一件令人惊讶的事情。我的错,问题中的代码检查器是JSHint,而不是JSLint。我将编辑post.Side注释:我建议不要在DOM元素(您的
link.team=…
part)上使用expando属性。
link.addEventListener("click", function (e) {
    updateForm(link.team);
});    
/*jshint esversion: 6 */
/*global updateForm, teams, table */

// Note that this function returns a function containing a closure
// that maintains one `link` per call.
function myListenerFactory(link) {
    return function (e) {
        updateForm(link.team);
    };
}

for (let i = 0; i < teams.length; i++) {
    let row = table.insertRow(-1);
  
    //removed code that made cells under the row
  
    let link = document.createElement("a");
    link.setAttribute("href","#form");
    link.team = teams[i];
    
    // Use the same function each time. Note that it's called IMMEDIATELY,
    // returning a new function for each iteration.
    link.addEventListener("click", myListenerFactory(link)()); // <<< Same function reused in the loop
    
    link.textContent = teams[i].name;
    
    //code that adds the link and other elements into the cells of the table
}
/*jshint esversion: 6 */
/*global updateForm, teams, table */

function myEventHandler(e) {
    // No need to backdoor `link` when we can derive it from `e`!
    updateForm(e.target.team);
}

for (let i = 0; i < teams.length; i++) {
    let row = table.insertRow(-1);
  
    //removed code that made cells under the row
  
    let link = document.createElement("a");
    link.setAttribute("href","#form");
    link.team = teams[i];
    
    // Use the same function each time
    link.addEventListener("click", myEventHandler);
    
    link.textContent = teams[i].name;
    
    //code that adds the link and other elements into the cells of the table
}