为何该DOM事件触发操作未造成无限循环?
为什么
wrapperHandler里的domInner.click()没触发无限循环? 先把你的代码清晰列出来,方便分析:
HTML结构
<div id="wrapper"> wrapper <div id="inner"> inner </div> </div>
JavaScript代码
var domInner = document.querySelector('#inner') var domWrapper = document.querySelector('#wrapper') domInner.onclick = innerHandler function innerHandler () { console.log('inner') } domWrapper.onclick = wrapperHandler function wrapperHandler () { console.log('wrapper') domInner.click() } domInner.click()
其实直接跑这段代码,是会触发递归调用的,但不会真的“无限”循环下去——原因和JavaScript的调用栈机制有关:
JavaScript的调用栈有最大深度限制(不同浏览器的数值不一样,比如Chrome大概是一万次上下)。当你在wrapperHandler里调用domInner.click(),会同步触发新一轮的click事件:先执行innerHandler,然后事件冒泡到wrapper再次触发wrapperHandler,这样层层递归,调用栈会越来越深。一旦超过浏览器允许的最大深度,就会抛出RangeError: Maximum call stack size exceeded的错误,直接终止递归,所以你看不到无限循环持续下去。
另外看你代码里注释掉了setTimeout,如果把domInner.click()放到setTimeout里,情况会变:异步调用不会占用当前的调用栈,而是把事件放到下一个事件循环里执行,这时候不会触发栈溢出,但会无限循环下去(控制台会不断输出inner和wrapper),直到你关闭页面或者手动终止脚本。
还有一种小概率情况:如果你的代码写法有误(比如不小心把console.log和domInner.click()都写到注释里了,导致wrapperHandler是空函数),那自然不会有任何递归调用,也就不会出现循环。不过从你的问题描述来看,应该是第一种调用栈限制的情况。
内容的提问来源于stack exchange,提问作者Theer
相关产品推荐
相关产品推荐

