this.id 未定义。我在编码经典井字游戏时遇到此错误

this.id is undefined. I get this error while coding the classic tic tac toe

提问人:Ramón Fo 提问时间:2/7/2023 最后编辑:Ramón Fo 更新时间:2/7/2023 访问量:210

问:

我正在尝试用这个调用磁贴 id。id 来自另一个函数中的 EventListener。

喜欢这个:

const setGame = () => {
    board = [
        [' ', ' ', ' '],
        [' ', ' ', ' '],
        [' ', ' ', ' ']
    ]

    for(let r = 0 ; r < 3; r++) {
        for(let c = 0 ; c < 3; c++) {
            let tile = document.createElement("div")
            tile.id = r.toString() + "-" + c.toString();
            tile.classList.add("col-4", "box", "d-flex", "justify-content-center", "align-items-center");
            
            tile.addEventListener("click", setTile);
            document.getElementById("board").append(tile);
        }
    }
}

const setTile = () => {
    if (gameOver) {
        return;
    }
    let coords = this.id.split("-")  //splits the id string "1-1" into an array["1", "1"]
    let r = parseInt(coords[0]);
    let c = parseInt(coords[1]);

    board[r][c] = currPlayer;
    this.innerText = currPlayer;

}

我不是“这个”的专家......我知道它从一个类中调用一个对象......在这种情况下,当我单击正在创建的 div 元素时,它将调用 tile 对象。但是在控制台上出现此错误:

Uncaught TypeError: this.id is undefined
    setTile http://127.0.0.1:5501/js/game.js:54
    setGame http://127.0.0.1:5501/js/game.js:43
    onload http://127.0.0.1:5501/js/game.js:27
    EventHandlerNonNull* http://127.0.0.1:5501/js/game.js:26

使用第一个函数 setGame()..我创建创建 3 x 3 板的 div,并为每个 div id 提供 0,0、0,1、0、2、1,0 等 id。等。并添加一个事件侦听器,以便当我们单击其中任何一个时。它执行以下函数 setTile()

当在单击时调用 setTile() 时,我期望从 tiles(div 元素)获取 id,调用 tile 将字符串转换为数组并使用它们来告诉 html 当前玩家在棋盘上的位置。this.

JavaScript 函数 这个 井字

评论

3赞 Scott Hunter 2/7/2023
你希望引用什么对象,为什么?this
0赞 Ramón Fo 2/7/2023
要平铺...tile.addEventListener(“点击”, setTile);
0赞 Ramón Fo 2/7/2023
因为使用 setTile( ) 我试图获取它的 id,然后稍后对它做一些事情......
1赞 mykaf 2/7/2023
“箭头函数没有自己与 、 或 的绑定,不应用作方法。”Arrow 函数文档thisargumentssuper
0赞 Ramón Fo 2/7/2023
我将箭头函数更改为正常函数,它起作用了!!多谢!!

答:

0赞 Santi Trayko 2/7/2023 #1

在这种情况下,您应该在“setTile”回调函数中捕获事件,而不是使用它。

尝试在事件回调中执行此更改。

还要检查您的“board”数组是否在回调函数的范围内。


const setTile = (event) => {
    if (gameOver) {
        return;
    }
    let coords = event.target.id.split("-")  //splits the id string "1-1" into an array["1", "1"]
    let r = parseInt(coords[0]);
    let c = parseInt(coords[1]);

    board[r][c] = currPlayer;
    this.innerText = currPlayer;

}

0赞 Emiel Zuurbier 2/7/2023 #2

这可以通过多种方式解决。但首先您需要知道箭头函数表达式的处理方式与正则函数表达式不同。因此,在您的函数中,将引用作为包装代码的第一个正则函数表达式或对象。thissetTilethiswindow

除此之外,在事件处理程序中使用可能很难理解,因为除了已添加事件侦听器的元素之外,还可以引用许多内容。thisthis

最简单的解决方法是将元素作为参数传递给函数,并使用 passed 而不是 .tilesetTiletilethis

const setGame = () => {
  board = [
    [' ', ' ', ' '],
    [' ', ' ', ' '],
    [' ', ' ', ' ']
  ];

  const boardElement = document.getElementById("board");

  for (let r = 0; r < 3; r++) {
    for (let c = 0; c < 3; c++) {
      let tile = document.createElement("div")
      tile.id = r.toString() + "-" + c.toString();
      tile.classList.add("col-4", "box", "d-flex", "justify-content-center", "align-items-center");

      tile.addEventListener("click", () => {
        setTile(tile);
      });

      boardElement.append(tile);
    }
  }
}

const setTile = (tile) => {
  if (gameOver) {
    return;
  }

  let coords = tile.id.split("-") //splits the id string "1-1" into an array["1", "1"]
  let r = parseInt(coords[0]);
  let c = parseInt(coords[1]);

  board[r][c] = currPlayer;
  tile.innerText = currPlayer;
}