Javascript 动态创建的元素EventListener上的对象修改问题

Javascript 动态创建的元素EventListener上的对象修改问题,javascript,Javascript,在使用Vanilla Javascript对动态创建的元素使用事件侦听器时,我遇到了一个非常有趣的问题。我将首先定义问题,然后发布代码 我使用javascript创建动态html元素,在创建过程中,我在每个新创建的对象上添加“单击”事件侦听器。在这个事件监听器中,我改变了一个全局对象的不同属性。我的意思是,当您单击一个动态创建的元素时,每个元素都会修改这个全局对象的不同属性 问题出现在这里,我动态地选择全局对象的不同属性。因此,对于每个元素,它都会修改全局对象的不同属性。但是当我运行代码时,我看

在使用Vanilla Javascript对动态创建的元素使用事件侦听器时,我遇到了一个非常有趣的问题。我将首先定义问题,然后发布代码

我使用javascript创建动态html元素,在创建过程中,我在每个新创建的对象上添加“单击”事件侦听器。在这个事件监听器中,我改变了一个全局对象的不同属性。我的意思是,当您单击一个动态创建的元素时,每个元素都会修改这个全局对象的不同属性

问题出现在这里,我动态地选择全局对象的不同属性。因此,对于每个元素,它都会修改全局对象的不同属性。但是当我运行代码时,我看到每个元素只更改全局对象的最新属性。这意味着每个元素都会更改该对象的相同属性,并且是该对象的最新属性。代码如下:

var filter = {1:false, 4:false, 7:false, 11:false, 8:false} //global object
var productsAndIndexes = {a:1, b:4, c:7, d:11, e:8 } //another global object used for looping 
function createEmptyFilter(){
  var hdr = document.querySelector("div.content .headers");
  for(var product in productsAndIndexes){
    var inp = document.createElement("input");
    inp.setAttribute("type", "checkbox");
    var filterInd = productsAndIndexes[product];

    inp.addEventListener("click" , (e) => {
      if(e.target.checked){
        filters[ filterInd ] = true;
      }else{
        filters[ filterInd ] = false;
      }
    });

    hdr.appendChild(inp);
  }
}
createEmptyFilter();
每次我选中一个复选框,我都会得到filter={1:false,4:false,7:false,11:false,8:true}。但是,每个复选框都应该修改其在对象中的相关部分

任何关于这个问题的解释和解决方案都是非常感谢的(尽管我不是15岁的代表:)
谢谢

问题是您的
filterid
变量是用
var
声明的,这意味着它是函数作用域,而不是for循环块的作用域。这意味着每个循环迭代都将覆盖相同的变量,因此单击处理程序都将覆盖相同的变量,而不是具有不同值的唯一变量。使用
const
let
声明它,然后
单击
处理程序将引用循环迭代的唯一值

既然您使用的浏览器足够现代,可以支持
=>
,那么您可能支持
let
const
;现在真的没有很好的理由使用
var

const filter = {1:false, 4:false, 7:false, 11:false, 8:false} //global object
const productsAndIndexes = {a:1, b:4, c:7, d:11, e:8 } //another global object used for looping 
function createEmptyFilter(){
  const hdr = document.querySelector("div.content .headers");
  for (let product in productsAndIndexes) {
    const inp = document.createElement("input");
    inp.setAttribute("type", "checkbox");
    const filterInd = productsAndIndexes[product];

    inp.addEventListener("click", e => {
      if (e.target.checked) {
        filters[filterInd] = true;
      } else {
        filters[filterInd] = false;
      }
    });

    hdr.appendChild(inp);
  }
}
createEmptyFilter();

我几乎能理解,但你说这是因为var是函数作用域还是因为“闭包”?既然事件监听器使用自己的函数,而且fillterInd处于匿名事件监听器函数的关闭状态,它的作用域是什么?它使用的是实际的filterId变量,而不是值?但即使我直接在事件侦听器函数中使用productsAndIndexes[product],也会得到相同的结果。虽然productsAndIndexes是一个全局变量,但它给出的结果与我使用函数变量时的结果相同?这是因为它们是函数范围的,而闭包引用的是函数范围的变量。在您尝试的情况下,
product
也是函数作用域,因此当循环通过时,下一个迭代值被分配给相同的
product
变量。因此,当单击处理程序运行时,它们引用最近分配的值(循环中的最后一个值)是循环的一个方便的替代方法,因为在
forEach
回调中,
product
是它自己的自变量,所以它里面的任何内联函数都会超过独特的
product
值。非常感谢,我现在完全得到了它