【问题标题】:Why do I need a wrapper function to recursively call with setTimeout为什么我需要一个包装函数来递归调用 setTimeout
【发布时间】:2018-05-17 03:58:34
【问题描述】:

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

(我知道 requestAnimationFrame 通常用于这类事情,但我正在尝试通过不同的方法熟悉 javascript)。

function moveThing(pos){
    var currentPos = pos;

    currentPos += 5;

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

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

    console.log(currentPos);
    setTimeout(function(){moveThing(currentPos)}, 100);

}

moveThing(0);

另外,如果我没有使用正确的术语,请随时更正。提前感谢您的帮助!

【问题讨论】:

  • 你还会做什么?
  • 因为setTimeout 期望一个可调用函数作为第一个参数,而不是函数call
  • @Li357 哦,好吧。够简单!谢谢:D

标签: javascript html css recursion settimeout


【解决方案1】:

基本上,答案是:因为您需要将一个函数传递给setTimeoutsetTimeout(moveThing(currentPos), 100) 将调用 moveThing 并将其 return 值(不是函数)传递给 setTimeout

但请注意,在任何现代浏览器上,您都可以传递moveThing 本身,您不需要包装器。你可以用这个替换你当前的setTimeout 电话:

setTimeout(moveThing, 100, currentPos);

...告诉setTimeout 在 100 毫秒(左右)内调用 moveThing,并将 currentPos 作为其第一个参数。

【讨论】:

    【解决方案2】:

    如果你这样做了:

    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>

    【讨论】:

      猜你喜欢
      • 2018-06-04
      • 1970-01-01
      • 2021-01-23
      • 2018-07-13
      • 2010-11-17
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 2012-01-22
      相关资源
      最近更新 更多