事件监听器调用的函数能否访问父作用域变量?JavaScript作用域疑问
问题核心原因
你碰到的现象本质是**JavaScript采用词法作用域(静态作用域)**导致的:函数的作用域链在函数声明定义的位置就已经确定,和函数运行时的调用位置无关。
- 内联回调函数是直接定义在
main函数内部的,它的作用域链包含main函数的作用域,所以可以直接访问main内定义的value变量。 - 而
handleClick是定义在全局作用域的,它的作用域链只有自身函数作用域、全局作用域,没有包含main函数的作用域,所以哪怕是在内联回调中调用它,也无法访问到main内的value变量。
除传参外的其他实现方案
方案1:将handleClick定义在main函数内部
直接把handleClick的声明放到main内,它的作用域链就会包含main的作用域,可以直接访问value:
function main(){ const value="lorem" function handleClick(){ console.log("clicked") console.log(value) } document.addEventListener("click",handleClick) } main()
方案2:使用Function.prototype.bind预设参数
通过bind方法可以预先给handleClick传入参数,不需要在触发回调的匿名函数内手动传参:
function handleClick(value){ console.log("clicked") console.log(value) } function main(){ const value="lorem" document.addEventListener("click", handleClick.bind(null, value)) } main()
方案3:使用高阶函数生成带闭包的处理函数
定义一个高阶函数接收value,返回真正的事件处理函数,返回的函数会持有对value的闭包引用:
function createHandleClick(value){ return function(){ console.log("clicked") console.log(value) } } function main(){ const value="lorem" document.addEventListener("click", createHandleClick(value)) } main()
方案4:将变量挂载到公共共享对象上(不推荐)
可以将value挂载到全局对象、或者事件绑定的DOM元素的自定义属性上,handleClick内直接读取即可,缺点是容易造成全局污染或者命名冲突:
function handleClick(){ console.log("clicked") console.log(document.customValue) } function main(){ const value="lorem" document.customValue = value document.addEventListener("click", handleClick) } main()
内容的提问来源于stack exchange,提问作者lorem1213
相关产品推荐
相关产品推荐

