我一直认为,由于JavaScript是单线程的,我可以附加事件处理程序,而不必担心处理程序在执行代码时会被执行。令我惊讶的是,我发现他们可以。根据{{3}},“无响应脚本”对话框可能会导致在脚本仍在运行时引发事件
我使用以下代码对此进行了测试:
<script>
function loop() {
var cond;
onblur = function (event) {
cond = false;
};
cond = true;
while (cond)
;
alert('loop exited!');
}
</script>
<button onclick="loop()">loop()</button>
在Firefox 11.0中,该功能在单击“继续”后打印“循环退出”。循环似乎暂停,允许执行事件。这类似于暂时更改目标线程上下文的(jsFiddle)。但它更危险,因为它允许改变外部状态。
这是一个错误吗?我是否应该不再依赖JavaScript的单流执行模型并确保我的所有脚本都是可重入的?或者这是一个不值得追求的缺陷,尽管主要的浏览器允许这种情况发生?
答案 0 :(得分:2)
所以是的,如果你创建一个无限循环,你将挂起你的JavaScript。差异浏览器将以不同的方式处理我的Firefox 11会抛出一个窗口,说明你的脚本已挂起。 Chrome目前正在为我旋转。
这应该证明了这一点。切勿在FF11或Chrome 17中拨打alert()
。
while(true){}
alert("sucks");
您询问了JavaScript中的同步语句。还有一些其他同步语句将阻止JavaScript的执行,如alert()
,confirm()
,同步ajax调用等。
您通常希望避免使用JavaScript中的任何同步内容!如果您想要暂停,您可能需要重新考虑设计。 JavaScript是事件驱动的。你不需要它在while循环中旋转,因为页面上的没有可以工作,包括点击等任何事件。
答案 1 :(得分:0)
我认为当你开始处理事件时会出现问题。
不要使用while循环,而应考虑使用递归函数。
以下是我对您的代码所做的一些修改,应该根据需要执行。
<head>
<script>
function loop(that) {
var cond;
that.onblur = function (event) {
cond = false;
};
cond = true;
var loop = 0
var xy = function x (){
if(cond == true){
loop++;
setTimeout(function(){xy()},0);
} else {
alert('loop exited! - '+loop);
return true;
}
}
xy();
}
</script>
</head>
<body>
<button onclick="this.focus(); loop(this)">loop()</button>
</body>
使用带有0延迟的setTimeout()应该允许任何事件跳入而没有任何问题。你的循环代码不会被执行得那么快,你只需要测试它就可以看到。