如何优化我的JavaScript井字棋代码使其更整洁?
井字棋代码优化建议
你的井字棋功能正常,但代码存在不少重复逻辑和冗余操作,以下是具体的优化方向和改进后的代码:
核心优化点
1. 批量处理重复的DOM元素选择
原代码中逐个获取sn0到sn8的DOM节点,可通过属性选择器批量获取,避免重复代码:
// 替换逐个选择的sn0-sn8 const snCells = document.querySelectorAll('[id^="sn"]');
2. 简化玩家状态存储
不需要创建<p>元素存储玩家名称,直接用字符串变量即可,减少DOM操作开销:
// 替换原有的currentPlayer DOM元素定义 const PLAYER_TOMATO = "tomato"; const PLAYER_FLOWER = "flower"; let currentPlayer = PLAYER_TOMATO;
3. 消除重复的类操作逻辑
checkWinner和restartGame中大量重复的类添加/移除代码,可通过循环批量处理:
- 在
checkWinner中:
// 替换原有的9个if判断 snCells.forEach((cell, index) => { cell.classList.remove(PLAYER_TOMATO, PLAYER_FLOWER); if (options[index] === PLAYER_TOMATO) { cell.classList.add(PLAYER_TOMATO); } else if (options[index] === PLAYER_FLOWER) { cell.classList.add(PLAYER_FLOWER); } });
- 在
restartGame中:
// 替换原有的9次类移除操作 snCells.forEach(cell => { cell.classList.remove(PLAYER_TOMATO, PLAYER_FLOWER); });
4. 使用符合规范的自定义属性
将HTML中的cellIndex改为data-cell-index(符合HTML5自定义属性规范),获取方式改为:
const cellIndex = this.dataset.cellIndex;
5. 优化变量与常量的可读性
将魔法字符串(如"tomato"、"flower")定义为常量,后续修改更方便,代码可读性更高。
优化后的完整代码
const cells = document.querySelectorAll(".cell"); const statusText = document.querySelector("#statusText"); const restartBtn = document.querySelector("#restartBtn"); const snCells = document.querySelectorAll('[id^="sn"]'); // 定义玩家常量,避免魔法字符串 const PLAYER_TOMATO = "tomato"; const PLAYER_FLOWER = "flower"; const winConditions = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; let options = Array(9).fill(""); let currentPlayer = PLAYER_TOMATO; let running = false; initializeGame(); function initializeGame() { cells.forEach(cell => cell.addEventListener("click", cellClicked)); restartBtn.addEventListener("click", restartGame); updateStatusText(); running = true; } function cellClicked() { const cellIndex = this.dataset.cellIndex; if (options[cellIndex] !== "" || !running) { return; } updateCell(this, cellIndex); checkWinner(); } function updateCell(cell, index) { options[index] = currentPlayer; cell.textContent = currentPlayer; } function changePlayer() { currentPlayer = currentPlayer === PLAYER_TOMATO ? PLAYER_FLOWER : PLAYER_TOMATO; updateStatusText(); } function updateStatusText() { statusText.textContent = `${currentPlayer}'s turn`; } function checkWinner() { let roundWon = false; for (const condition of winConditions) { const [a, b, c] = condition; const cellA = options[a]; const cellB = options[b]; const cellC = options[c]; if (cellA === "" || cellB === "" || cellC === "") continue; if (cellA === cellB && cellB === cellC) { roundWon = true; break; } } if (roundWon) { statusText.textContent = `${currentPlayer} wins!`; running = false; } else if (!options.includes("")) { statusText.textContent = `Draw!`; running = false; } else { changePlayer(); } // 批量更新snCells的类 snCells.forEach((cell, index) => { cell.classList.remove(PLAYER_TOMATO, PLAYER_FLOWER); if (options[index] === PLAYER_TOMATO) { cell.classList.add(PLAYER_TOMATO); } else if (options[index] === PLAYER_FLOWER) { cell.classList.add(PLAYER_FLOWER); } }); } function restartGame() { currentPlayer = PLAYER_TOMATO; options = Array(9).fill(""); updateStatusText(); cells.forEach(cell => cell.textContent = ""); running = true; // 批量移除snCells的类 snCells.forEach(cell => { cell.classList.remove(PLAYER_TOMATO, PLAYER_FLOWER); }); }
内容的提问来源于stack exchange,提问作者ljaskolka
相关产品推荐
相关产品推荐

