Node.js运行报错'Warrior未定义'及'GetAttackResult未定义'的修复求助
解决你的JavaScript OOP游戏代码错误
让我们一步步拆解你遇到的问题,先搞定核心的ReferenceError: Warrior is not defined和GetAttackResult not defined错误,顺便修正一些隐藏的语法问题:
错误原因分析与修复步骤
1. 类声明无提升,导致Warrior未定义
JavaScript里类声明不会像函数声明那样被提升。你在代码最开头直接调用了Main(),但此时Warrior和Battle类还没被解析定义,运行时自然找不到它们。
修复:把Main()的调用移到所有类定义的后面,确保类已经被加载完成后再创建实例。
2. 类方法调用方式错误,导致GetAttackResult未定义
GetAttackResult是Battle类的成员方法,你在StartFight里直接用GetAttackResult(warrior1, warrior2)调用,会被当作全局函数查找,肯定找不到。必须用this.GetAttackResult()来调用当前Battle实例的方法。
3. Math.random缺少括号,导致计算逻辑失效
Math.random是一个函数,必须加()才能生成0到1之间的随机数。你写的Math.round(Math.random * 50)会把函数本身当作数值计算,结果是NaN,攻击值和格挡值也就完全无效了。
4. 模板字符串换行的语法隐患
你在console.log里的模板字符串直接换行,虽然语法上允许,但容易引发编辑器或解释器的解析问题,建议用\n显式换行,让代码更规范。
5. 类方法的语法规范调整
ES6类语法中,类的方法不需要加function关键字,直接定义方法名即可,这样代码更符合现代JS的写法规范。
修正后的完整代码
class Warrior { constructor(name, health) { this.name = name; this.health = health; } Attack() { let attackValue = Math.round(Math.random() * 50); return attackValue; } Block() { let blockValue = Math.round(Math.random() * 10); return blockValue; } } class Battle { StartFight(warrior1, warrior2) { while (true) { if (this.GetAttackResult(warrior1, warrior2) === "Game Over") { console.log("Game Over"); break; } if (this.GetAttackResult(warrior2, warrior1) === "Game Over") { console.log("Game Over"); break; } } } GetAttackResult(warriorA, warriorB) { let warA_attack = warriorA.Attack(); let warB_block = warriorB.Block(); let dmg2warB = warA_attack - warB_block; // 避免出现负数伤害(格挡成功时不会回血) if (dmg2warB < 0) dmg2warB = 0; warriorB.health -= dmg2warB; if (dmg2warB > 0) { console.log(`${warriorA.name} attacks ${warriorB.name} and deals ${dmg2warB} damage.`); console.log(`${warriorB.name} has ${warriorB.health} health.\n`); } else { console.log(`${warriorB.name} blocked ${warriorA.name}'s attack completely!\n`); } if (warriorB.health <= 0) { console.log(`${warriorB.name} has died and ${warriorA.name} is victorious!`); return "Game Over"; } else { return "Fight Again!"; } } } function Main() { let apple = new Warrior("Apple", 3000); let microsoft = new Warrior("Microsoft", 3000); let battle = new Battle(); battle.StartFight(apple, microsoft); } // 最后调用入口函数,确保类已定义完成 Main();
额外优化说明
- 增加了伤害值判断,当格挡值大于攻击值时,伤害设为0,避免出现不合理的回血情况。
- 添加了格挡成功的提示信息,让战斗过程更清晰直观。
- 调整了变量命名(比如
hi改成battle),提升代码可读性。
现在用Node.js运行这段代码,就能正常模拟战斗过程啦!
内容的提问来源于stack exchange,提问作者Abhinav Jha
相关产品推荐
相关产品推荐

