如何通过onclick事件修改全局作用域变量解决未定义报错
问题原因
你的报错和全局变量更新无关,核心是JavaScript同步执行逻辑+异步事件的时序错位:
- 页面加载时JS会从上到下执行所有顶层作用域的代码,你写在末尾的伤害计算行
let daño = (Eleccion.ataque - monstruo.defensa);会在页面刚打开时立刻运行 - 此时用户还没点击任何角色选择按钮,
Eleccion仅完成声明未赋值,初始值为undefined,直接读取undefined的ataque属性会直接抛出类型错误,代码执行在这一行直接中断 - 后续你点击按钮确实会给全局
Eleccion正确赋值,控制台也能读到更新后的值,但伤害计算的代码早在页面加载阶段就已经因报错终止,不会等你点击完成后自动重新执行,才会出现"点完按钮变量还是读不到"的错觉。
修复方法
不要在顶层作用域直接写依赖用户点击结果的逻辑,把计算逻辑封装成函数,等用户完成选择、点击事件触发时再调用:
let Eleccion; // 把伤害计算逻辑封装为独立函数,仅在需要时调用 function calcularDaño() { // 增加判空兜底,避免未选角色时误调用报错 if (!Eleccion) { alert("请先选择角色后再计算伤害"); return; } const daño = Eleccion.ataque - monstruo.defensa; // 此处编写后续需要用到伤害值的业务逻辑,比如进入战斗、渲染数值等 console.log("计算得到伤害值:", daño); return daño; } // 每个角色选择的点击回调中,给Eleccion赋值完成后再调用计算函数 function clickTanque() { Eleccion = { ...tanque }; alert("Has seleccionado " + Eleccion.nombre); calcularDaño(); // 此时Eleccion已完成赋值,不会出现undefined问题 } function clickSoldado() { Eleccion = { ...soldado }; alert("Has seleccionado " + Eleccion.nombre); calcularDaño(); } function clickGuerrero() { Eleccion = { ...guerrero }; alert("Has seleccionado " + Eleccion.nombre); calcularDaño(); } function clickVikingo() { Eleccion = { ...vikingo }; alert("Has seleccionado " + Eleccion.nombre); calcularDaño(); } // 原有绑定事件的代码不需要改动 tanqueSel.addEventListener("click", clickTanque); soldadoSel.addEventListener("click", clickSoldado); guerreroSel.addEventListener("click", clickGuerrero); vikingoSel.addEventListener("click", clickVikingo);
可选优化
你当前四个点击回调逻辑高度重复,可以通过配置映射的方式简化代码,减少冗余:
// 建立选择按钮和对应角色数据的映射关系,无需编写4个重复的回调函数 const selectorList = [ { element: tanqueSel, roleData: tanque }, { element: soldadoSel, roleData: soldado }, { element: guerreroSel, roleData: guerrero }, { element: vikingoSel, roleData: vikingo } ]; selectorList.forEach(item => { item.element.addEventListener("click", () => { Eleccion = { ...item.roleData }; alert("Has seleccionado " + Eleccion.nombre); calcularDaño(); }) })
内容的提问来源于stack exchange,提问作者JhulianR
相关产品推荐
相关产品推荐

