JavaScript - 递归setInterval两次调用父函数 - 为什么?

时间:2014-01-19 21:56:46

标签: javascript recursion memory-leaks setinterval

我在HTML5 doc的头部有这么简单的代码:

var lol = 0;

function madeMyDay() {
  lol++;
  console.log(lol);
  setInterval(madeMyDay, 1000);
}

该功能首次从此调用:

<script>
  madeMyDay();
</script>

在一些div之后 - 在div加载之后运行它,而不是等待整个文档。

我期待的是看到以下内容:

1 (at start)
2 (after 1 sec)
3 (after 2 sec)
4 (after 3 sec)
...

但我明白了:

1  (at start)
2  (after 1 sec)
3  (after 2 sec)
4  (after 2 sec, together with 3)
5  (after 3 sec)
6  (after 3 sec, together with 5)
7  (after 3 sec, together with 5)
8  (after 3 sec, together with 5)
9  (after 4 sec)
10 (after 4 sec, together with 9)
11 (after 4 sec, together with 9)
12 (after 4 sec, together with 9)
13 (after 4 sec, together with 9)
14 (after 4 sec, together with 9)
15 (after 4 sec, together with 9)
16 (after 4 sec, together with 9)
...

这当然会导致浏览器因内存泄漏而在几分钟内崩溃(如果不是几十秒)。

看起来setInterval会调用父函数两次 - 我不知道为什么以及如何防止这种奇怪的行为?

我尝试了setTimeout - 它正确地完成了工作。 setInterval的魔力是什么,我不明白?

PS。 - 在Kubuntu最近的Chrome上测试

3 个答案:

答案 0 :(得分:2)

你想使用setTimeout(),因为它只调用一次函数。

这允许你做递归位以保持它继续。

否则,setInterval()会在间隔上重复函数调用,因此单次调用

setInterval(function () {console.log(Date.now()), 1000);

将每秒重复一次。

编辑:向您展示setInterval()的工作原理,这也是您问题的有效解决方法:

var lol = 0;

setInterval(madeMyDay, 1000);

function madeMyDay() {
  lol++;
  console.log(lol);
}

注意这里没有递归。 setInterval()执行重复。

答案 1 :(得分:1)

将setInterval更改为setTimeout

function madeMyDay() {
  lol++;
  console.log(lol);
  setTimeout(madeMyDay, 1000);
}

答案 2 :(得分:0)

您可以在设置间隔之前检查是否已定义间隔。

var lol = 0;

function madeMyDay() {
  lol++;
  console.log(lol);
  if(typeof myInterval == "undefined") {
    var myInterval = setInterval(madeMyDay, 1000);
  }
}