开发JS海战游戏时报Cannot read 'classList' of undefined错误如何解决
错误原因
- 核心是
generate函数中随机起始位置randomStart的计算逻辑错误,会导致索引超出AISquares数组的合法范围(0~99),取到undefined后访问classList属性就抛出了对应错误。具体问题点有2个:- 计算
randomStart时错误添加了Math.abs,且没有根据船的当前摆放方向(水平/垂直)限制最大起始值:垂直摆放的船长是船长*10,原代码只减去了水平方向的船长,导致垂直摆放时起始位置过大,randomStart + index超过数组最大索引99。 - 方向判断逻辑完全失效:
if (current === 0)、if (current === 1)的判断对象current是数组,永远不可能等于数字0/1,这段代码不会生效,后续用到direction变量时会出问题。
- 计算
修复代码
将原generate函数替换为如下代码即可解决偶发报错问题:
function generate(ship) { let randomDirection = Math.floor(Math.random() * ship.directions.length); let current = ship.directions[randomDirection]; const shipLength = ship.directions[0].length; // 根据方向计算最大合法起始位置 let maxStart = randomDirection === 0 ? AISquares.length - shipLength : AISquares.length - shipLength * widthl; // 修正随机起始位置计算逻辑,移除多余的Math.abs let randomStart = Math.floor(Math.random() * maxStart); const isTaken = current.some(index => AISquares[randomStart + index].classList.contains("taken")) // 修正边缘判断逻辑:水平方向才需要判断左右边缘,垂直方向不需要 let isAtRightEdge = false, isAtLeftEdge = false; if (randomDirection === 0) { isAtRightEdge = current.some(index => (randomStart + index) % widthl === widthl - 1 ) isAtLeftEdge = current.some(index => (randomStart + index) % widthl === 0) } if (!isTaken && !isAtRightEdge && !isAtLeftEdge) { current.forEach(index => AISquares[randomStart + index].classList.add("taken", ship.name)) } else { generate(ship) } }
额外优化建议
可以把递归调用改成循环,避免极端情况下递归层数过多导致栈溢出:
function generate(ship) { while(true) { let randomDirection = Math.floor(Math.random() * ship.directions.length); let current = ship.directions[randomDirection]; const shipLength = ship.directions[0].length; let maxStart = randomDirection === 0 ? AISquares.length - shipLength : AISquares.length - shipLength * widthl; let randomStart = Math.floor(Math.random() * maxStart); const isTaken = current.some(index => AISquares[randomStart + index].classList.contains("taken")) let isAtRightEdge = false, isAtLeftEdge = false; if (randomDirection === 0) { isAtRightEdge = current.some(index => (randomStart + index) % widthl === widthl - 1 ) isAtLeftEdge = current.some(index => (randomStart + index) % widthl === 0) } if (!isTaken && !isAtRightEdge && !isAtLeftEdge) { current.forEach(index => AISquares[randomStart + index].classList.add("taken", ship.name)) break; } } }
内容的提问来源于stack exchange,提问作者FedFer
相关产品推荐
相关产品推荐

