【问题标题】:Javascript "clearInterval" method cannot stop the timer when defined outside of window.onload在 window.onload 之外定义时,Javascript“clearInterval”方法无法停止计时器
【发布时间】:2019-01-10 21:28:17
【问题描述】:

我在 window.onload = function(){...} 之外声明了一个包含 setInterval 的函数和一个包含 clearInterval 的函数。但是计时器无法按预期停止

当我单击开始按钮时,我可以看到计时器正确启动,并且控制台中正在重复打印“hello”。但是,当我点击“停止”按钮时,计时器不会被清除。

我认为在加载文档时,“start_btn”和“stop_btn”的onclick函数应该准备好了,然后我使用开始按钮,它将变量“timer”设置为一个数字,然后我点击停止按钮,为什么看不到当前非空的“定时器”变量?

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Demo</title>
    <style>
      *{
        margin: 0px;
        padding: 0px;
      }
    </style>
    <script type="text/javascript">
      window.onload = function(){
        var timer = null;
        var start_btn = document.getElementById("start");
        var stop_btn = document.getElementById("stop");

        startFunc(start_btn, timer);
        stopFunc(stop_btn, timer);

      };

      function startFunc(target, timer){
        target.onclick = function(){
          timer = setInterval(function(){
            console.log("hello");
          }, 300);
        };
      }

      function stopFunc(target, timer){
        target.onclick = function(){
          clearInterval(timer);
        };
      }

    </script>
  </head>
  <body>
    <button type="button" id="start">start</button>
    <button type="button" id="stop">stop</button>
  </body>
</html>

【问题讨论】:

  • 您的startFunc 只是在修改timer 的本地副本。考虑扩大它的范围或传递一个对象,以便在作为参数传递时可以改变它。
  • 感谢您,这对您有很大帮助!

标签: javascript


【解决方案1】:

就像 CollinD 在评论中所说的那样,问题是 timer 的范围,您可以通过使 timer 成为外部范围的一部分来使事情正常工作

var timer = null;
window.onload = function(){
  var start_btn = document.getElementById("start");
  var stop_btn = document.getElementById("stop");

  startFunc(start_btn);
  stopFunc(stop_btn);

};

function startFunc(target){
  target.onclick = function(){
    timer = setInterval(function(){
      console.log("hello");
    }, 300);
  };
}

function stopFunc(target){
  target.onclick = function(){
    clearInterval(timer);
  };
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Demo</title>
    <style>
      *{
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
  <body>
    <button type="button" id="start">start</button>
    <button type="button" id="stop">stop</button>
  </body>
</html>

原因是 setInterval 返回 int 是间隔的 ID 而不是对象,所以发送的是变量的副本而不是变量本身


如果您不希望它成为外部范围的一部分,那么您需要发送它具有类似的object,因为它们是自己发送的,而不是通过副本发送的:

window.onload = function(){
  var timer = {a: null}
  var start_btn = document.getElementById("start");
  var stop_btn = document.getElementById("stop");

  startFunc(start_btn, timer);
  stopFunc(stop_btn, timer);

};

function startFunc(target, timer){
  target.onclick = function(){
    timer.a = setInterval(function(){
      console.log("hello");
    }, 300);
  };
}

function stopFunc(target, timer){
  target.onclick = function(){
    clearInterval(timer.a);
  };
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Demo</title>
    <style>
      *{
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
  <body>
    <button type="button" id="start">start</button>
    <button type="button" id="stop">stop</button>
  </body>
</html>

【讨论】:

  • 那么是不是说在startFunc的栈帧中,有一个变量“timer”,而在栈帧stopFunc中,又有一个变量“timer”,它们是不同的变量?为什么当变量 timer 是一个对象时这有效,但当 timer 是原始类型时无效?是堆内存的原因吗?
  • @Mr.Snail 这是因为,就像我说的,原始类型是作为自身的副本发送的,而对象是自己发送的。这就是我所知道的大多数语言的工作原理,我认为这是因为复制一些对象可能是一个坏主意,就像你说的堆内存一样,但老实说我不知道​​深层原因。
  • 好的,这让我现在更清楚了。非常感谢您的代码!
  • @Mr.Snail 也将 JavaScript 作为一种特殊性,允许您将属性添加到原语 (let x = 1; x.a = 42;) 但在发送到函数的值是原语 1 并且 42 丢失的情况下跨度>
猜你喜欢
  • 1970-01-01
  • 2023-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多