使用Javascript - element.addEventListener()返回“遗漏的类型错误”

问题描述 投票:1回答:1

对于情况下,我想编写一个记忆游戏,你必须对的两个相同颜色的圆圈,直到整个板是完整的。我把它叫做匹配两种。下面是我将从引用的代码:

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对象从我的html文档元素引用(有16个圆圈和他们每个人都有circle0,CIRCLE1,CIRCLE2 ..等的ID,然后在有一个小的算法,以确保只有两个矩阵中的每个颜色,使他们都有一个匹配对在for循环每次迭代中,我添加事件侦听到每个圆圈。如果点击了一圈,我希望它改变其颜色存储在颜色[I]。颜色然而,当我点击圈子中的所有返回是:

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...

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

javascript html css
1个回答
0
投票

你的问题可以归结为这样JS对待var变量 - 样的,他们“泄漏”到全球范围内。

想想看,你已经附加了事件侦听器:

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

所以,每当听众被触发,它调用main()函数,并将circle[i]进去。但由于i是这就是所谓范围向外泄漏的变量,它总是有16的价值 - for循环的最后一次迭代中分配给它的价值。这就是为什么main()函数试图访问styleundefined属性 - 它是在传递给它的circle[16]的价值。

这里有一对夫妇的方式来解决这个问题:

如果你可以使用ES6 let变量:

let i循环使用var i代替for的:

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

如果没有,用函数闭包的经典方式:

function createListener(j) {
  return function () {
    main(circle[j])
  }
}
// and use it in your 'for' loop later:
circle[i].elem.addEventListener('click', createListener(i));

下面是提供了更多的技术来避免这样的有用话题:JavaScript closure inside loops – simple practical example

© www.soinside.com 2019 - 2024. All rights reserved.