简体   繁体   English

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

[英]Javascript - element.addEventListener() returns “Uncaught TypeError”

For context, I am trying to code a memory game where you have to pair two of the same colored circles until the whole board is complete. 就上下文而言,我正在尝试编写一个记忆游戏,其中您必须将两个相同颜色的圆圈配对,直到整个棋盘完成为止。 I've called it Match-Two. 我称它为Match-Two。 Here is the code that I'll reference from: 这是我将从中引用的代码:

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

So in this code I create a class of Circle and I create an array of Circle objects which is identified as 'circle'. 因此,在此代码中,我创建了Circle类,并创建了一个Circle对象数组,这些对象被标识为“ circle”。 When the page is loaded, I give each circle object an element reference from my html document (There are 16 circles and they each have an id of circle0, circle1, circle2.. etc. Then there's a small algorithm to ensure there are only two of each color in the matrix so they all have a matching pair. In each iteration of the for loop, I add an event listener to each circle. If the circle is clicked, I want it to change to its color which is stored in color[i].color. However, when I click the circles all it returns is: 加载页面时,我给每个圆形对象一个来自我的html文档的元素引用(有16个圆形,它们每个都有一个id,分别为circle0,circle1,circle2 ..等。然后有一个小的算法来确保只有两个矩阵中每种颜色的颜色,因此它们都有一个匹配对。在for循环的每次迭代中,我向每个圆添加一个事件侦听器。如果单击该圆,则希望它更改为以颜色存储的颜色[i] .color。但是,当我单击圆圈时,它返回的只是:

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

Which is referencing: 指的是:

circle.elem.style.backgroundColor = circle.color;

So I put some console.log() functions in to see what was going on: 所以我放了一些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])
    });
}

And this spits out exactly what I expect: 这正好符合我的期望:

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

So it returns the element reference and the color of the circle. 因此,它返回元素参考和圆的颜色。 So then I try putting the "circle[i].elem.style.backgroundColor = circle[i].color" into the event listener and I get the same issue as before... 因此,然后我尝试将“ 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
    });
}

Circles without their colors. 没有颜色的圆圈。 The console log statements are on the right-hand side with their specific colors as well... 控制台日志语句也以其特定的颜色显示在右侧...

So I gave up and decided to write that exact line of code outside the event listener to see if that works, and it changed all the circle's colors to their specific 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
    });
}

The circles with their specific colors... 具有特定颜色的圆圈...

There is some problem the event listener not being able to pass the object of a Circle or something... I don't know please help :( 事件侦听器无法传递Circle对象或某些对象,这有一些问题。我不知道,请帮助:(

Your problem boils down to the way JS treats var variables - they sort of "leak" into the global scope. 您的问题归结为JS处理var变量的方式-它们有点“泄漏”到全局范围中。

Consider the event listener that you've attached: 考虑您已附加的事件侦听器:

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

So, whenever the listener gets triggered, it calls main() function and passes circle[i] into it. 因此,无论何时触发了侦听器,它都会调用main()函数,并将circle[i]传递给该函数。 But since i is the variable that's leaked outside of the supposed scope, it always has the value of 16 - the value assigned to it during the last iteration of the for loop. 但是由于i是在假定范围之外泄漏的变量,因此它始终具有16的值-在for循环的最后一次迭代期间分配给它的值。 That's why the main() function tries to access a style property of undefined - it's the value of circle[16] that was passed into it. 这就是为什么main()函数尝试访问undefinedstyle属性的原因-这是传递给它的circle[16]的值。

Here's a couple of ways to fix it: 有几种解决方法:

If you can use ES6 let variables: 如果可以使用ES6 let变量:

Use let i instead of var i in your for loop: 在您的for循环中使用let i代替var i

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

If not, a classic way with function closure: 如果不是,则采用函数关闭的经典方式:

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

Here's a useful topic that provides more techniques to avoid this: JavaScript closure inside loops – simple practical example 这是一个有用的主题,提供了更多避免这种情况的技术: 循环内的JavaScript闭合–简单的实际示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 element.addEventListener 多次触发 - element.addEventListener fires multiple times 具有element.addEventListener的event.target - event.target with element.addEventListener stopPropagation:element.addEventListener vs onclick属性 - stopPropagation: element.addEventListener vs onclick attribute document.addEventListener 与 element.addEventListener 的问题 - Problems with document.addEventListener vs element.addEventListener Firefox element.event 有效但 element.addEventlistener 无效 - Firefox element.event works but element.addEventlistener does not JavaScript 未捕获类型错误:replay.addEventListener 不是 function - JavaScript Uncaught TypeError: replay.addEventListener is not a function addEventListener错误:未捕获的TypeError - addEventListener error: Uncaught TypeError addEventListener scroll Uncaught TypeError: element.getBoundingClientRect is not a function - addEventListener scroll Uncaught TypeError: element.getBoundingClientRect is not a function 未捕获的TypeError:无法在JavaScript Webshare API中读取null的属性“ addEventListener” - Uncaught TypeError: Cannot read property 'addEventListener' of null in JavaScript webshare api Javascript:未捕获的TypeError:无法调用null的方法&#39;addEventListener&#39; - Javascript: Uncaught TypeError: Cannot call method 'addEventListener' of null
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM