最近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>

解决方案 »

  1.   

    oBut.onclick这说明了你只有点击按钮之后方法才能执行。。
      

  2.   

    谢谢回复啊,我说的问题就是在oBut点击后出现的呀
      

  3.   

    楼主试试
     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);
      };
      

  4.   

    这个可以,谢谢了 不过不知道我的那个while循环哪里错了,感觉没错啊
      

  5.   

    其实并不是while循环条件错了。。是因为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);改成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已经跳出了。
      

  6.   

    兄弟,能说具体点吗,我在setInterval里面设置了count=0,那么按照正常顺序的话,应该可以进行下一次while循环啊,为什么只执行一次循环呢?
      

  7.   

    难道while循环结束了,循环体里面的setInterval函数还可以继续执行?
      

  8.   

    简单来说,看下面例子
    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同理
      

  9.   

    <!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()
      {  
      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>
      

  10.   


    可以这么说,你的想法是while里面会等setInterval定时器跑完才会执行下面的代码,其实他并不会这样的
      

  11.   

    你的思维是正确的,但是做法错了。第一,你想用while来循环多个div下落,又用setInterval来执行下落过程,这本身没甚么。
    但是用while嵌套setInterval,就导致执行时机不一致。
    严重的误解了setInterval函数while循环的条件,是!count,但已进入循环,就count++了,直至循环结束,都是count都是等于1,造成循环条件错误。虽然你在setInterval里面将count=0,但是它是延迟执行的,while循环都结束了,再去把循环条件改成“真”又有啥用?
      

  12.   

    其实楼上这解释有点牵强。
    虽然你在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
      

  13.   

    非也,即使设成0,也是延迟执行总所周知,js中setTimeout、setInterval的过程是链式执行,凡事调用了这两个函数中的任意一个,必将会在函数链中新增一个待执行的函数,哪怕是把延迟事件设置成0。
      

  14.   


    你所谓的延迟是指一种怎么样的状态呢?也许你理解的和我理解的一样,但是我觉得这种说法会造成一种误会
    var count = 0;
    while(!count) {
       setTimeout(function(){
           count = 0
       },0)
       //这里做很多很耗时间的操作
      
    }
    别人误会以为setTimeout里面的函数会在while循环完毕前执行。。所以我觉得按你说的必将会在函数链中新增一个待执行的函数,其实就是js线程队列里面新增一个待执行的函数。。根据线程来理解会比较清晰
      

  15.   

    大神我想问下ajax请求onreadystatechange中执行的代码是否和setTimeout延迟执行函数占用进程队列的方式类似呢?
      

  16.   

    onreadystatechange中与setTimeout在队列中是不一样的。根据我的理解
    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是完全不一样的。如果有其他高手有不同见解,欢迎拍砖