JavaScript中如何在if-else块内访问前序分支变量解决未定义报错
问题根因
报错本质是JavaScript作用域规则导致的边界问题:
- 当前
var_2声明在div1分支内部的check函数的局部作用域中,属于函数内部变量,else if分支完全不在它的作用域链上,自然无法访问- 原代码还存在隐藏作用域bug:函数末尾的
button.addEventListener("click", check)同样会在走div2分支时报错,因为check函数也是定义在div1的if块内部的局部函数- 即便把
var_2用let/const声明在if块内部,它也只属于div1的块级作用域,在else分支依然无法访问
可落地的修正方案
把需要跨分支共享的变量、函数统一提到foo函数的顶层作用域声明,让所有if/else分支、以及函数末尾的公共代码都能正常访问,修正后的示例代码如下:
function foo(shown) { // 顶层声明所有跨分支共享的变量,设置初始默认值 let var_2 = null; let check = null; if (shown == "div1") { // 给共享变量赋值、给共享的check函数赋值 check = function() { var_2 = new Date().toISOString(); console.log("time", window.var_1 + " - " + var_2); } // 差异化命名不同按钮,避免同名变量混淆 const btn2 = document.getElementById("button2"); btn2.addEventListener("click", check); } else if (shown == "div2") { const var_3 = new Date().toISOString(); // 此时var_2已经在顶层声明,可正常访问 // 如果用户从未触发div1分支下的button点击,var_2会保持初始的null值 console.log("time:", var_2 + " - " + var_3); } const btn = document.getElementById("button"); // 做空值判断,避免div2分支下check为空时报错 if (check) { btn.addEventListener("click", check); } return true; }
注意事项
- 如果
var_2的业务逻辑就是存储用户在div1分支下点击button2产生的时间戳,那要接受它的赋值时机:只有用户真的触发过对应点击事件,它才会有有效值,从未触发时输出初始值是符合业务逻辑的 - 尽量避免使用
var声明变量,它的变量提升特性很容易引发跨作用域的意料之外的引用问题,优先用let/const做声明,作用域边界更清晰 - 重复的同名
button变量建议改成差异化命名,减少代码维护时的混淆成本
内容的提问来源于stack exchange,提问作者aywoki
相关产品推荐
相关产品推荐

