目前通过在循环调用中移动元素x像素量来测试一些东西。我已经创建了一个递归函数,并添加了一些延迟以避免回调溢出。我用setTimeout来创建这个延迟。我想知道为什么我需要在使用setTimeout时将我的递归函数包装在另一个函数中。如果不这样做,则不会添加延迟,浏览器会在我的控制台中执行回调错误。下面是我正在使用的代码。它的目的是让“东西(一个球)”从左到右,一遍又一遍地穿过div / box / screen。
(我理解requestAnimationFrame通常用于此类事情,但我试图通过不同的方法熟悉javascript。)
collide_point
另外,如果我没有使用正确的术语,请随意纠正。在此先感谢您的帮助!
答案 0 :(得分:3)
从根本上说,答案是:因为你需要将一个函数传递给setTimeout
。 setTimeout(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>