JavaScript中函数与事件监听回调内变量声明的差异问题
问题1解答
你能在全局直接访问btn是浏览器的专属特性:所有设置了id属性的DOM元素,会被自动挂载到window全局对象上,成为同名全局变量,所以哪怕你没有手动声明btn,也能在全局作用域直接拿到id为btn的DOM元素对象。
而x是用var关键字声明在declareX立即执行函数内部的变量,var声明的变量遵守函数作用域规则:仅在声明它的函数内部可访问,函数外部的作用域无法读取内部声明的变量,所以最后一行打印x会抛出未定义错误。
问题2解答
addEventListener的回调函数内部用var btn = ...重新声明了一个同名的局部变量,这个局部变量会覆盖全局作用域的btn变量:
- 回调函数外部访问的是全局挂载的
btn,值就是对应的DOM元素对象 - 回调函数内部访问的是当前函数作用域下新声明的
btn,你给它赋值为DOM的innerHTML,所以打印出来的是按钮的内容
这里涉及var的变量提升规则:哪怕你把var btn的声明写在函数中间,JS在预编译阶段也会把这个声明提升到当前函数作用域的顶部,所以整个函数内部访问的btn都是局部变量,不会用到全局的。
复现代码
console.log(btn); // 打印按钮元素本身 btn.addEventListener('click', () => { var btn = document.getElementById('btn').innerHTML; console.log(btn); // 打印按钮的innerHTML内容 }); (function declareX() { var x = 0; console.log(x); // 打印0 })(); console.log(x); // 报错:x未定义
内容的提问来源于stack exchange,提问作者Asmaa Mahmoud
相关产品推荐
相关产品推荐

