为什么我需要一个包装函数来递归调用setTimeout

时间:2017-12-03 16:38:17

标签: javascript html css recursion settimeout

目前通过在循环调用中移动元素x像素量来测试一些东西。我已经创建了一个递归函数,并添加了一些延迟以避免回调溢出。我用setTimeout来创建这个延迟。我想知道为什么我需要在使用setTimeout时将我的递归函数包装在另一个函数中。如果不这样做,则不会添加延迟,浏览器会在我的控制台中执行回调错误。下面是我正在使用的代码。它的目的是让“东西(一个球)”从左到右,一遍又一遍地穿过div / box / screen。

(我理解requestAnimationFrame通常用于此类事情,但我试图通过不同的方法熟悉javascript。)

collide_point

另外,如果我没有使用正确的术语,请随意纠正。在此先感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

从根本上说,答案是:因为你需要将一个函数传递给setTimeoutsetTimeout(moveThing(currentPos), 100)会调用moveThing并将其返回值(不是函数)传递给setTimeout

但请注意,在任何模糊的现代浏览器上,您都可以传递moveThing本身,而不需要包装器。您可以使用以下代码替换当前的setTimeout来电:

setTimeout(moveThing, 100, currentPos);

...告诉setTimeout在{1}}作为第一个参数传递100ms(或左右)时调用moveThing

答案 1 :(得分:1)

如果你这样做了:

setTimeout(moveThing(currentPos), 100);

你会立即调用它,它实际上与此相同:

var x = moveThing(currentPos);
setTimeout(x, 100);

因此该函数永远不会被延迟,并且永远不会退出,并且最终会达到调用堆栈限制。

如果你这样做了:

setTimeout(moveThing, 100);

然后它会被延迟,但由于currentPos变量是函数的本地变量,它不会被传递,所以它不起作用。

每次不涉及传递包装函数的一个选项是使moveThing关闭currentPos变量。然后函数可以直接传递,它将始终访问相同的var。

function makeMover(pos, theThing) {
  return function moveThing() {
    pos += 5;

    theThing.style.left = pos + "px";

    if (Math.abs(pos) >= 900) {
      pos = -500;
    }

    console.log(theThing.id, pos);
    setTimeout(moveThing, 100);
  }
}

var mover = makeMover(0, document.querySelector("#theThing"));
mover();

var mover2 = makeMover(0, document.querySelector("#theThing2"));
setTimeout(mover2, 1000);
.thing {
  position: relative;
  width: 30px;
  height: 30px;
  background-color: orange;
}
#theThing2 {
  background-color: blue;
}
<div id=theThing class=thing></div>
<div id=theThing2 class=thing></div>