Javascript-element.addEventListener()返回;未捕获类型错误“;

Javascript-element.addEventListener()返回;未捕获类型错误“;,javascript,html,css,Javascript,Html,Css,在上下文中,我试图编写一个记忆游戏,在这个游戏中,你必须配对两个相同颜色的圆圈,直到整个棋盘完成。我称之为第二场比赛。下面是我将从中引用的代码: class Circle { constructor(element, circleColor){ this.elem = element; this.color = circleColor; } } var frequency = [0, 0, 0, 0, 0, 0, 0, 0]; var num;

在上下文中,我试图编写一个记忆游戏,在这个游戏中,你必须配对两个相同颜色的圆圈,直到整个棋盘完成。我称之为第二场比赛。下面是我将从中引用的代码:

class Circle {
    constructor(element, circleColor){
        this.elem = element;
        this.color = circleColor;
    }
}
var frequency = [0, 0, 0, 0, 0, 0, 0, 0];
var num; 
var hue = new Array(8);
var circle = new Array(16);

hue[0] = "#0039ff";
hue[1] = "#ff0000";
hue[2] = "#43ff00";
hue[3] = "#fffa00";
hue[4] = "#7405b5";
hue[5] = "#ff9d00";
hue[6] = "#ff00c3";
hue[7] = "#00fff6";

onload = function() {
    for(var i = 0; i < 16; i++){
        circle[i] = new Circle(document.getElementById("circle" + i));
        while(circle[i].color === undefined){
            num = Math.floor(Math.random() * 8);
            if(frequency[num] != 2){
                frequency[num]++;
                circle[i].color = hue[num];   
                circle[i].elem.addEventListener('click', function(){
                    main(circle[i])
                });
            }
        }
    }
}
function main(circle){
    circle.elem.style.backgroundColor = circle.color;
}
因此,我在其中放入了一些console.log()函数,以查看发生了什么:

if(frequency[num] != 2){
    frequency[num]++;
    circle[i].color = hue[num];   
    console.log(circle[i].elem);
    console.log(circle[i].color);
    circle[i].elem.addEventListener('click', function(){
        main(circle[i])
    });
}
这正是我所期望的:

script.js:31 #ff9d00
script.js:30 div data-brackets-id=​"11" class=​"circle" id=​"circle1" /div
script.js:31 #ff9d00
script.js:30 div data-brackets-id=​"12" class=​"circle" id=​"circle2" /div
script.js:31 #0039ff
script.js:30 div data-brackets-id=​"13" class=​"circle" id=​"circle3" /div
script.js:31 #0039ff
因此它返回元素引用和圆的颜色。因此,我尝试将“circle[I].elem.style.backgroundColor=circle[I].color”放入事件侦听器,我得到了与之前相同的问题

if(frequency[num] != 2){
    frequency[num]++;
    circle[i].color = hue[num];   
    console.log(circle[i].elem);
    console.log(circle[i].color);
    circle[i].elem.addEventListener('click', function(){
        circle[i].elem.style.backgroundColor = circle[i].color
    });
}

所以我放弃了,决定在事件监听器之外编写那行代码,看看它是否有效,它将所有圆圈的颜色都更改为它们的特定颜色

if(frequency[num] != 2){
    frequency[num]++;
    circle[i].color = hue[num];   
    console.log(circle[i].elem);
    console.log(circle[i].color);
    circle[i].elem.style.backgroundColor = circle[i].color;
    circle[i].elem.addEventListener('click', function(){
        circle[i].elem.style.backgroundColor = circle[i].color
    });
}


事件侦听器无法传递圆或其他对象时出现问题。。。我不知道,请帮忙:(

你的问题归结为JS对待
var
变量的方式——它们有点“泄漏”到全局范围

考虑已附加的事件侦听器:

circle[i].elem.addEventListener('click', function(){
  main(circle[i])
});
因此,每当监听器被触发时,它调用
main()
函数并传递
circle[i]
进入它。但由于
i
是泄漏到假定范围之外的变量,因此它的值始终为
16
——在
for
循环的最后一次迭代中分配给它的值。这就是
main()
函数尝试访问
未定义的
样式
属性-传递给它的是
圆圈[16]
的值

以下是几种修复方法:

如果可以使用ES6
let
变量: 在
for
循环中使用
let i
而不是
var i

for (let i = 0; i < 16; i++) {
  //...
}

这里有一个有用的主题,提供了更多的技术来避免这种情况:

您的问题归结为JS处理
var
变量的方式——它们有点“泄漏”到全局范围

考虑已附加的事件侦听器:

circle[i].elem.addEventListener('click', function(){
  main(circle[i])
});
因此,每当监听器被触发时,它调用
main()
函数并传递
circle[i]
进入它。但由于
i
是泄漏到假定范围之外的变量,因此它的值始终为
16
——在
for
循环的最后一次迭代中分配给它的值。这就是
main()
函数尝试访问
未定义的
样式
属性-传递给它的是
圆圈[16]
的值

以下是几种修复方法:

如果可以使用ES6
let
变量: 在
for
循环中使用
let i
而不是
var i

for (let i = 0; i < 16; i++) {
  //...
}

这里有一个有用的主题,它提供了更多的技术来避免这种情况:

您能否再次生成此错误消息,然后复制它所指向的代码行(在过去的某个时候是第39行)并将其粘贴到您的问题中,这样我们就可以看到哪个代码触发了错误?
uncaughttypeerror:cannotread属性'elem'of undefined at main(script.js:39)
尝试在for循环声明中使用
let i=0
而不是
var i=0
,您是否可以再次生成此错误消息,然后复制它所指向的代码行(在过去的某个时候是第39行)并将其粘贴到您的问题中,以便我们可以看到哪个代码触发了错误?
uncaughttypeerror:无法读取main(script.js:39)未定义的属性“elem”
尝试在for循环声明中使用
let i=0
而不是
var i=0
function createListener(j) {
  return function () {
    main(circle[j])
  }
}
// and use it in your 'for' loop later:
circle[i].elem.addEventListener('click', createListener(i));