Javascript 为什么';在click事件侦听器中触发click()是否会导致无限循环?

Javascript 为什么';在click事件侦听器中触发click()是否会导致无限循环?,javascript,html,addeventlistener,Javascript,Html,Addeventlistener,有人能解释一下这个JavaScript代码的程序流程吗: const$leaveRoom=document.querySelector(“#离开按钮”); 设a=1; $leaveRoom.addEventListener('单击',()=>{ 控制台日志(a); 控制台日志(“检查”); a++; $leaveRoom.click(); 控制台日志(a); a++; }); 离开房间 这个问题的关键是每个元素上都有一个隐藏标志 每个元素都有一个相关的点击进度标志,该标志最初未设置。 文件:

有人能解释一下这个JavaScript代码的程序流程吗:

const$leaveRoom=document.querySelector(“#离开按钮”);
设a=1;
$leaveRoom.addEventListener('单击',()=>{
控制台日志(a);
控制台日志(“检查”);
a++;
$leaveRoom.click();
控制台日志(a);
a++;
});
离开房间
这个问题的关键是每个
元素上都有一个隐藏标志

每个元素都有一个相关的点击进度标志,该标志最初未设置。

文件:

一旦激活此方法,此标志将从
proges Status==unset
更改为
proges Status==active
(伪代码)

(一旦包含的代码完全执行,它将返回到初始状态)

当此标志处于
活动
状态时,将忽略对此方法的任何调用


这是我的原始帖子,展示了`console.log()的执行顺序`
const bt_leaveRoom=document.querySelector(“#离开按钮”)
变量计数器=0
变量来源='event clic'
bt_leaveRoom.addEventListener('click',()=>
{
让源=原点
log(`u first console.log():counter=${++counter},origin=${source}`)
来源='call'
bt_leaveRoom.单击()
log(`second console.log():counter=${++counter},origin=${source}`)
})

离开房间
我尝试了几种方法来找到这个问题的答案。对于这里发生的事情,我还没有找到一个明确的答案,但我相信我在这里分享的东西会导致这个极好的问题

我简化了代码,将重点放在事件的递归触发上

简化代码

const$leaveRoom=document.querySelector(“#离开按钮”);
设a=1;
$leaveRoom.addEventListener('单击',()=>{
console.log(a++);
$leaveRoom.click();
});
离开房间
const click1=document.querySelector(“#click1”)
const click2=document.querySelector(“#click2”)
const click3=document.querySelector(“#click3”)
click1.addEventListener('click',(事件)=>{
控制台日志(“单击1”)
点击2.点击()
});
click2.addEventListener('click',(事件)=>{
console.log(“单击2”)
点击3.点击()
});
click3.addEventListener('click',(事件)=>{
控制台日志(“单击3”)
点击1.点击()
});
点击1
点击2

单击3
您正在处理递归类型函数。(一个调用自身的函数)不完全是这样,而是有点像。单击1并检查是否输出。然后程序调用click函数并输出2和check。然后,第一次单击的第二部分输出3,最后是对单击函数的内部调用的第二部分输出4@DCR“然后第一次点击的第二部分输出”-但为什么它不会触发新的点击呢?它为什么会存在?@DCR-到底是什么让这段代码不是传统的递归?我不确定OP在问什么。这段代码中最有趣的部分似乎可以归结为“为什么在元素自己的事件处理程序中调用
el.click()
不会引发无限的事件链?”否决票可能是因为不清楚在这里执行操作会有什么意外,因此,我假设它是单击调用,而不是增量或延迟的final
console.log
s,也可以在没有事件的情况下进行说明。典型的递归有一个结束情况,以及一种在每次迭代中减少问题直到到达结束情况的方法。这并不能回答问题。为什么在函数中调用$leaveRoom.click()不会创建一个无止境的循环?基本上,第二个console.log()语句似乎永远都不应该出现executed@MisterJojo的第一段代码非常棒,谢谢。但是我不能理解你写的第二段代码的意义…[如果(源代码)='call')]部分。你能解释一下吗?你明白了,点击进度标志是关键。让这个问题在你的回答中更加突出怎么样?与开始时一样,在规范中明确引用“如果设置了此元素的点击进度标志,则返回”,并提醒调用HtmleElement.click()会同步调用事件处理程序?那么,为什么不删除其余的部分,因为它实际上没有增加多少内容呢?@kaido我留下了第二个
console.log()
,以尊重PO问题,并显示执行的逻辑延续。但这是真的,不是很好useful@TusharAgarwal
setTimeout
在一个单独的进程中工作,即使选择的延迟为零,此调用也会延迟到足以完成所有要执行的指令的时间,因此此
标志
会返回到之前的
未设置状态
。在他的示例中,
setTimeout
是最后一条指令,这足以使
标志返回到
unset
。另一方面,如果后面有其他指令,则
标志
将不会返回到
unset
,调用将被拒绝。但是,除非您在
设置超时中设置足够长的延迟时间,否则chrome会对来自脚本的用户输入事件施加限制?而且,这种行为在不同浏览器之间似乎是一致的。这44次真的很可疑。我想知道是什么原因造成了这个限制。你也是44次吗?这是一个如此随机的数字……是的,这取决于引擎。我猜这是一些内部队列或堆栈大小限制。正如您所说的@Bergi,它肯定依赖于引擎。在Chrome和Edge中,我得到44个计数,然后在控制台中记录一个错误“超过最大调用堆栈大小”。在FireFox中,它运行383次,然后在控制台中记录一个错误“未定义”。