最近js学习,做了一个小程序,思路是首先创建一个div,让它自动下落,等落到页面底部时,再创建一个div,也让它自动下落,一直这样循环。但是程序执行时只有一个div下落,没有后续的div运动过程,并且程序中的while循环貌似只循环一次,不明白怎么回事(被js的程序执行顺序搞晕了),各位大侠帮帮忙吧,谢谢了<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
<script type="text/javascript">
window.onload=function ()
{
var oBut=document.getElementById("but");
oBut.onclick=function()
{
var count=0;
while (!count)
{
var oDiv=document.createElement("div");
oDiv.style.background="red";
oDiv.style.position="absolute";
oDiv.style.width="50px";
oDiv.style.height="50px";
document.body.appendChild(oDiv);
count++;
var timer=setInterval(function (){
oDiv.style.top=oDiv.offsetTop+50+"px";
if(oDiv.offsetTop>=document.documentElement.clientHeight-oDiv.offsetHeight)
{
oDiv.style.top=document.documentElement.clientHeight-oDiv.offsetHeight+"px";
count=0;
clearInterval(timer);
//alert(count);
}
},500);
}
};
};</script>
</head><body>
<input id="but" type="button" value="Start"></input>
</body></html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
<script type="text/javascript">
window.onload=function ()
{
var oBut=document.getElementById("but");
oBut.onclick=function()
{
var count=0;
while (!count)
{
var oDiv=document.createElement("div");
oDiv.style.background="red";
oDiv.style.position="absolute";
oDiv.style.width="50px";
oDiv.style.height="50px";
document.body.appendChild(oDiv);
count++;
var timer=setInterval(function (){
oDiv.style.top=oDiv.offsetTop+50+"px";
if(oDiv.offsetTop>=document.documentElement.clientHeight-oDiv.offsetHeight)
{
oDiv.style.top=document.documentElement.clientHeight-oDiv.offsetHeight+"px";
count=0;
clearInterval(timer);
//alert(count);
}
},500);
}
};
};</script>
</head><body>
<input id="but" type="button" value="Start"></input>
</body></html>
oBut.onclick = function() {
var oDiv=document.createElement("div"),
_fn = arguments.callee;//获取当前函数
oDiv.style.background="red";
oDiv.style.position="absolute";
oDiv.style.width="50px";
oDiv.style.height="50px";
document.body.appendChild(oDiv);
var timer=setInterval(function (){
oDiv.style.top=oDiv.offsetTop+50+"px";
if(oDiv.offsetTop>=document.documentElement.clientHeight-oDiv.offsetHeight) {
oDiv.style.top=document.documentElement.clientHeight-oDiv.offsetHeight+"px";
clearInterval(timer);
_fn();
}
},500);
};
oDiv.style.top=oDiv.offsetTop+50+"px";
if(oDiv.offsetTop>=document.documentElement.clientHeight-oDiv.offsetHeight)
{
oDiv.style.top=document.documentElement.clientHeight-oDiv.offsetHeight+"px";
count=0;
clearInterval(timer);
//alert(count);}
},500);改成while (!count)
{
var oDiv=document.createElement("div");
oDiv.style.background="red";
oDiv.style.position="absolute";
oDiv.style.width="50px";
oDiv.style.height="50px";
document.body.appendChild(oDiv);
count++;
var timer=setInterval(function (){
oDiv.style.top=oDiv.offsetTop+50+"px";
if(oDiv.offsetTop>=document.documentElement.clientHeight-oDiv.offsetHeight)
{
oDiv.style.top=document.documentElement.clientHeight-oDiv.offsetHeight+"px";
count=0;
clearInterval(timer);
alert(2);}
},500);
alert(count)
}试下上面就知道了,是因为setTimeout,setInterval都不会阻塞线程,它只是把函数放到线程的尾部执行,JS是单线程的他这里将count=0这个赋值放到线程的最尾部,这是while已经跳出了。
var a = 0; //这里是操作f1
while(!a){ //while是操作f2
a++;
//dosth 随便写点操作
var str = "111";//这里看成是操作f3 var arr = [1,2];//这里看成是操作f4 setTimeout(function(){
//这里是操作f5
a = 0;
},1000)
}你的想法,执行顺序是f1==>f2(循环开始)==>f3==>f4==>f5==>f2(跳出循环)但因为setTimeout的作用并不是可以阻塞线程,它的作用是将f5放到线程的最末端,然后1000毫秒后执行这就变成 f1==>f2(循环开始)==>f3==>f4==>f2(跳出循环)==>f5setInterval同理
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
<script type="text/javascript">
window.onload=function ()
{
var oBut=document.getElementById("but");
oBut.onclick=function()
{
createDiv();
};
};function createDiv()
{
var oDiv=document.createElement("div");
oDiv.style.background="red";
oDiv.style.position="absolute";
oDiv.style.width="50px";
oDiv.style.height="50px";
document.body.appendChild(oDiv);
var timer=setInterval(function (){
oDiv.style.top=oDiv.offsetTop+50+"px";
if(oDiv.offsetTop>=document.documentElement.clientHeight-oDiv.offsetHeight)
{
oDiv.style.top=document.documentElement.clientHeight-oDiv.offsetHeight+"px";
count=0;
clearInterval(timer);
createDiv();
//alert(count);}
},500);
}
</script>
</head><body>
<input id="but" type="button" value="Start"></input>
</body></html>
可以这么说,你的想法是while里面会等setInterval定时器跑完才会执行下面的代码,其实他并不会这样的
但是用while嵌套setInterval,就导致执行时机不一致。
严重的误解了setInterval函数while循环的条件,是!count,但已进入循环,就count++了,直至循环结束,都是count都是等于1,造成循环条件错误。虽然你在setInterval里面将count=0,但是它是延迟执行的,while循环都结束了,再去把循环条件改成“真”又有啥用?
虽然你在setInterval里面将count=0,但是它是延迟执行的,while循环都结束了,再去把循环条件改成“真”又有啥用?
这里会让别人误以为如果我设置setInterval的速度很快很快,它就能正常工作,其实并不是这样的,就算毫秒数设置为0,效果都是一样的,这是由于js是单线程于setInterval与setTimeout工作原理的缘故可以测试下下面例子就知道了
var count = 0,
i = 0;
while(!count){
count++;
setTimeout(function(){
count = 0;
},0);//设置为0,可以说无延迟
i++;
}alert(i); //i 为1,说明就算设置为0,所谓无延迟的状态,setTimeout里面函数的还是会在while最后执行再看下面很简单的例子alert(1);// f1线程
setTimeout(function(){alert(2)}, 0); //f2
alert(3) //f3无论你在alert(1)弹出后等多少时间。执行顺序都还是f1==>f3==>f2打印结果为1,3,2
你所谓的延迟是指一种怎么样的状态呢?也许你理解的和我理解的一样,但是我觉得这种说法会造成一种误会
var count = 0;
while(!count) {
setTimeout(function(){
count = 0
},0)
//这里做很多很耗时间的操作
}
别人误会以为setTimeout里面的函数会在while循环完毕前执行。。所以我觉得按你说的必将会在函数链中新增一个待执行的函数,其实就是js线程队列里面新增一个待执行的函数。。根据线程来理解会比较清晰
js是单线程的,但ajax确实是异步的,这是因为ajax是浏览器建立一个http线程去请求服务器,而当数据返回时执行onreadystatechange这个回调函数,这个http线程是完全不受js线程影响的,举个例子setTimeout(function(){
alert(1);//操作f1
alert(12);//操作f2
},0)
alert(2); //操作f3
alert(3); //操作f4这时线程队列是f3==>f4==>f1==>f2; 无论setTimeout定时器里面毫秒数为多少都一样,f1操作无论如何都会等队列前面的操作完成后才执行下面看ajax//省略ajax请求方法
onreadystatechange = function(){
alert(1);//操作f1
alert(12);//操作f2
}
alert(2); //操作f3
alert(3); //操作f4
我没测试环境,楼上可以自己测试下,其实只要是http请求都可以,例如var img = new Image();img.onload都是一样的
如果onreadystatechange 与setTimeout一致的话,队列应该是f3==>f4==>f1==>f2,但他们其实是不一样的
它实际是2个线程队列:
1:js线程 f3==>f4
2:http线程 f1==>f2这2个线程互不影响
当f3操作足够长的时候(在这个例子就是f3一直不点确定), f1会在数据返回了后立刻执行,在这时候就会同时出现f3弹出框与f1弹出框,大家有没发现,一般情况下是不可能出现2个弹出框的,这是因为alert会阻塞当前线程的,当我们不点确定的情况下,是不会执行线程队列的下一个任务,但是http请求会开辟出一个新的线程,就形成了多线程的现象了,也解释了为什么会2个弹出框的现象了由上可知onreadystatechange 与setTimeout是完全不一样的。如果有其他高手有不同见解,欢迎拍砖