Javascript 从事件函数更改全局变量

Javascript 从事件函数更改全局变量,javascript,function,variables,tic-tac-toe,scope-chain,Javascript,Function,Variables,Tic Tac Toe,Scope Chain,我正在努力学习Javascript 我在Youtube上观看了一些Javascript课程,正在尝试创建我的第一个项目 项目应该是简单的井字游戏 功能: 第一次点击框应填写“X” 第二次单击另一个框时应填写“Y” 第三次单击另一个框时,应再次用“X”填充,依此类推,直到所有框都用字符填充 这是我的密码 HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8">

我正在努力学习Javascript

我在Youtube上观看了一些Javascript课程,正在尝试创建我的第一个项目

项目应该是简单的井字游戏

功能: 第一次点击框应填写“X” 第二次单击另一个框时应填写“Y” 第三次单击另一个框时,应再次用“X”填充,依此类推,直到所有框都用字符填充

这是我的密码 HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div class="main">
<table>
    <tr>
        <td class="b1-1"></td>
        <td class="b1-2"></td>
        <td class="b1-3"></td>
    </tr>
    <tr>
        <td class="b2-1"></td>
        <td class="b2-2"></td>
        <td class="b2-3"></td>
    </tr>
    <tr>
        <td class="b3-1"></td>
        <td class="b3-2"></td>
        <td class="b3-3"></td>
    </tr>
</table>
</div>
<script src="script.js" type="text/javascript"></script>
</body>
</html>
Javascript

var action = document.querySelectorAll('td');
var gameState = 0;
for (var i = 0; i <= action.length - 1; i++) {
    getClassName = "." + action[i].classList.value;
        if (gameState === 0) {
            document.querySelector(getClassName).addEventListener("click", chasviX(i));
        } else {
            document.querySelector(getClassName).addEventListener("click", chasviO(i));
        }
}

function chasviX(cord) {
        document.querySelector("." + action[cord].classList.value).addEventListener("click", event => {
            document.querySelector("." + action[cord].classList.value).textContent = "X";
            gameState = 1;
        });
};

function chasviO(cord) {
        document.querySelector("." + action[cord].classList.value).addEventListener("click", event => {
            document.querySelector("." + action[cord].classList.value).textContent = "O";
            gameState = 0;
        });
};
var action=document.querySelectorAll('td');
var配子状态=0;
对于(var i=0;i{
document.querySelector(“.”+操作[cord].classList.value).textContent=“X”;
配子状态=1;
});
};
功能chasviO(跳线){
document.querySelector(“.”+action[cord].classList.value).addEventListener(“单击”,事件=>{
document.querySelector(“.”+操作[cord].classList.value).textContent=“O”;
配子状态=0;
});
};
还有项目链接-

目前,每个盒子都充满了“X”。 我知道我不完全理解闭包和作用域链,但请给我一个正确的代码来通过示例理解它


提前感谢并致以最诚挚的问候。

因为您使用的是querySelectorAll,它将提供一个集合,所以您可以迭代该集合并直接向其中添加事件侦听器。另外,您正在添加多个eventlistener,这不是必需的

var action=document.querySelectorAll('td');
var配子状态=0;
action.forEach((项目)=>{
item.addEventListener('单击',(e)=>{
如果(游戏状态===0){
e、 target.textContent=“X”;
配子状态=1;
}否则{
e、 target.textContent=“0”;
配子状态=0;
}
})
})
.main{
填充:100px0;
宽度:360px;
保证金:0自动;
}
桌子
t车身{
保证金:0;
填充:0;
宽度:360px;
高度:360px;
}
tr{
宽度:360px;
高度:120px;
保证金:0;
填充:0;
}
运输署{
文本对齐:居中;
宽度:120px;
高度:120px;
边框:1px实心#333;
保证金:0;
填充:0;
字体大小:50px;
}

在这里,我制作了一个工作JSFIDLE:

我将JS部分简化为:

var gameState = 0; // Holds the current game state
var cells = document.getElementsByTagName("td"); // list of cells of the game board

// attach an event listener at each cell. 
for (var i=0;i<cells.length;i++) 
{    
    cells[i].addEventListener("click", chasvi);
}   

function chasvi() 
{
       // in event callbacks "this" refers to the element that triggered the event. In this case, it is the TD element.
       this.textContent = gameState ? "X" : "0";

       // switch the game state
       gameState = !gameState;

}
var gameState=0;//保持当前游戏状态
var cells=document.getElementsByTagName(“td”);//游戏板的单元格列表
//在每个单元格上附加一个事件侦听器。

对于(var i=0;i,您的错误在于,在进行任何移动之前,您创建事件的方式仅取决于
gameState
的当前值。您需要检查并更改事件中
gameState
的值:

var action = document.querySelectorAll('td');
var gameState = 0;
for (var i = 0; i <= action.length - 1; i++) {
    action[i].addEventListener("click", function() {
      this.textContent = (gameState = (gameState + 1) % 2) ? 'x' : '0';
  })
}
var action=document.querySelectorAll('td');
var配子状态=0;

for(var i=0;i您的解决方案的问题是,您编写的for循环将事件侦听器分配给板上的每个正方形,以便在板上设置一个“X”之前,甚至在板上单击一次。这意味着您的if逻辑永远不会分配一个“O”,因为所有单击都将调用
chasviX()

您应该使用
节点列表的
forEach()
函数,就像您的
操作
变量一样:

 var gameState = false;
 action.forEach(function(act) {
    act.addEventListener("click", function(event) {
        // If gameState is false(logical 0), place an 'X' on the board
        // Otherwise, place a 'O'
        event.target.textContent = gameState ? 'X' : 'O';
        // Invert state at the end
        gameState = !gameState;
    });
})

在您的第一个循环中:
for(var i=0;我最终发现了var和let之间的差异。您很好man@LevanSakvarelidze检查问题
 var gameState = false;
 action.forEach(function(act) {
    act.addEventListener("click", function(event) {
        // If gameState is false(logical 0), place an 'X' on the board
        // Otherwise, place a 'O'
        event.target.textContent = gameState ? 'X' : 'O';
        // Invert state at the end
        gameState = !gameState;
    });
})
for (var i = 0; i <= action.length - 1; i++) {
    (function(){
          let coor = i;
          let getClassName = "." + action[i].classList.value;
          document.querySelector(getClassName).addEventListener("click", function() { chasvi(coor); });
    }());
}
function chasvi(cord)
{
    let TextToDisplay;

    if (gameState === 0)
    {
        TextToDisplay = "X";
        gameState = 1;
    }
    else
    {
        TextToDisplay = "O";
        gameState = 0;
    }
    document.querySelector("." + action[cord].classList.value).textContent = TextToDisplay;
}
function chasvi(cord)
{
    let TextToDisplay;

    if (gameState === false)
    {
        TextToDisplay = "X";
    }
    else
    {
        TextToDisplay = "O";
    }
    gameState = !gameState; // This swaps the state true/false
    document.querySelector("." + action[cord].classList.value).textContent = TextToDisplay;
}
let TextToDisplay;

if (gameState === false)
{
    TextToDisplay = "X";
}
else
{
    TextToDisplay = "O";
}
let TextToDisplay = gameState ? "O" : "X"; // This means if gameState is true, then "O" is returned, else "X"