为什么把 clearInterval 放在外面清除不了 setInterval

谁能帮我一步步分析下JS的 " onmousedown事件 " 代码,指出问题所在.源代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style media="screen">
    body,div,ul,li{
      padding: 0;
      margin: 0;
      font-size: 0;
      letter-spacing: -4px;
      position: relative;
    }
    div.all{
      width: 400px;
      height: 12000px;
      margin: 0 auto;
      border: 1px solid black;
      /*overflow: hidden;*/
    }
      div span.totop{
        display: block;
        color: #fff;
        background-color: rgba(0, 0, 0, 0.5);
        cursor: pointer;
        position: fixed;
        text-align: center;
        width: 60px;
        height: 60px;
        line-height: 60px;
        font-size: 20px;
        letter-spacing: 0;
        left: 50%;
        bottom: 50px;
        margin-left: -30px;
      }
  </style>
</head>
<body>
  <div class="all">
    <span class="totop">顶部</span>
  </div>

  <script type="text/javascript">
    var spanTotop= document.querySelector("span.totop");

    var itimerAnother,
    iPosition;
    window.onscroll= function(){
      iPosition= document.documentElement.scrollTop|| document.body.scrollTop;
      console.log(iPosition);
    }

    spanTotop.onmousedown= function(){
      iPosition= document.documentElement.scrollTop|| document.body.scrollTop;
      itimerAnother= setInterval(function(){
        iPosition= iPosition- Math.ceil(iPosition/ 10);
        document.documentElement.scrollTop= iPosition;
        document.body.scrollTop= iPosition;
      },10);
      if(iPosition<= 0){
        clearInterval(itimerAnother);
        // 为什么把 clearInterval 放在外面清除不了 setInterval -------------------------
        // 放在 setInterval 里面就可以 ---------------------------
      }
    }
  </script>
</body>
</html>

先谢谢了...

阅读 6.7k
2 个回答

从新解释一下,在第一次mousedown的时候,假如iPosition大于0,此时不会执行clearInterval,执行setInterval,此时itimerAnother1,会一直执行下去。不会停止,此时再次点击mousedown,假如iPosition等于0,会又一次执行setInterval,此时itimerAnother2,并且会立刻clearInterval掉,但是itimerAnother1的对象一直都没有clearInterval掉,所以也不会停下来,要想解决这个问题,你把clearInterval(itimerAnother-1);加到clearInterval(itimerAnother)前面就可以了,

又试了一下,即使放到setInterval里面,你在iPosition向上滚动的时候,连续触发mousedown也会出现bug,解决方案有两个第一个,clearInterval放到setInterval里面,然后点击一次后禁止再触发mousedown,第二种方法onmosuedown改成下面的

var arr = []
spanTotop.onmousedown= function(){
  iPosition= document.documentElement.scrollTop|| document.body.scrollTop;
  itimerAnother= setInterval(function(){
    console.log(itimerAnother) 
    iPosition= iPosition- Math.ceil(iPosition/ 10);
    document.documentElement.scrollTop= iPosition;
    document.body.scrollTop= iPosition;
    if(iPosition<= 0){
      console.log(itimerAnother + 'haha')
      // 在这里需要clear掉所有创建的setInterval
      arr.forEach(function(ele) {
        clearInterval(ele)
      })
    }
  },10);
  arr.push(itimerAnother)
}

function(){

console.log('1') //同步

setInterval(function(){
//异步,将函数放到另一个队列,等当前任务都完成后,再开始执行异步的队列
console.log('2')
})

console.log('3') //同步
}


当3没完成是,2设置的函数不会执行,所以顺序是 1->3->2;

所以你是setInterval后,检测scrollTop,
但函数当前的任务(相当于上面的3)还没完成,所以setInterval里的函数还没执行,
scrollTop还是>0;所以不会清除,
clearInterval只执行1次,执行时scroll>0,清除失败
后面即使=0了,也不会执行clearInterval

放到setInterval里面,
每次循环都会执行clearInterval;
所以当scroll=0时,下一个循环的clearInterval,就会成功

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题