Javascript-element.addEventListener()返回“未捕获的TypeError”

时间:2019-02-03 02:10:35

标签: javascript html css

有关背景下,我想代码记忆游戏,你必须要对的两个相同颜色的圆圈,直到整个板是完整的。我称它为Match-Two。下面是代码,我会从参考:

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;
}

因此,在此代码中,我创建了一个Circle类,并创建了一个Circle对象数组,这些对象被标识为“ circle”。当加载页面时,我给每个圆圈对象从我的html文档元素引用(有16个圆圈和他们每个人都有circle0,CIRCLE1,CIRCLE2 ..等的ID,然后在有一个小的算法,以确保只有两个矩阵中的每个颜色,使他们都有一个匹配对在for循环每次迭代,我一个事件侦听器添加到每个圆圈。如果点击了一圈,我也想改变它的颜色存储在颜色[i] .color。但是,当我单击圆圈时,它返回的只是:

Uncaught TypeError: Cannot read property 'elem' of undefined
at main (script.js:39)
at HTMLDivElement.<anonymous> (script.js:31)

正在引用:

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

所以它返回元件和参考圆的颜色。于是我尝试把“圈子[I] .elem.style.backgroundColor =圈子[I]。颜色”到事件监听器,我也得到了同样的问题...

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
    });
}

Circles without their colors. The console log statements are on the right-hand side with their specific colors as well...

所以我放弃了并决定在事件侦听器外编写确切的代码行,以查看其是否起作用,然后它将所有圆圈的颜色更改为它们的特定颜色...

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
    });
}

The circles with their specific colors...

有一些问题不能够通过一个圆或某事的对象的事件监听器......我不知道,请帮助:(

1 个答案:

答案 0 :(得分:0)

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

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

circle[i].elem.addEventListener('click', function(){
  main(circle[i])
});

因此,只要触发了侦听器,它就会调用main()函数并将circle[i]传递给该函数。但是,由于i是泄漏到假定范围之外的变量,因此它始终具有16的值-在for循环的最后一次迭代期间分配给它的值。这就是main()函数试图访问style的{​​{1}}属性的原因-这是传递给其中的undefined的值。

以下是几种修复方法:

如果可以使用ES6 circle[16]变量:

let循环中使用let i代替var i

for

如果不是,则采用函数关闭的经典方式:

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

这是一个有用的主题,它提供了避免这种情况的更多技术:JavaScript closure inside loops – simple practical example