为什么这个javascript不断递归

oky*_*eni 0 javascript closures

我正在阅读javascript忍者列表5.6的秘密.在解释中,作者要求将变量移动到全局范围.然后,创建另一个id为box2的id,并在box1上的animate之后立即调用box2上的animate,以显示闭包为变量提供的保护.我理解这个概念,但我得到的结果是断言语句的无限递归.我不明白这一点.

为什么会这样?为什么它会进入无限递归循环?

代码如下.

谢谢!

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Listing 5.6</title>
  <script type="text/javascript" src="../scripts/assert.js"></script>
  <link href="../styles/assert.css" rel="stylesheet" type="text/css">
  <style type="text/css">
    #box { 
      position: absolute;
      border: 3px solid blue;
      width: 200px; height: 200px;
      background-color: #6495ed; 
      font-size: 2em; 
    }
  </style>
</head>
<body>
  <div id="box">????</div>                               <!--#1-->
  <div id="box2">????</div>                               <!--#1-->

  <script type="text/javascript">

    var elem;
    var tick;
    var timer;

    function animateIt(elementId) {

      elem = document.getElementById(elementId);              //#2
      tick = 0;                                               //#3

      timer = setInterval(function(){                         //#4
        if (tick < 100) {
          elem.style.left = elem.style.top = tick + "px";
          tick++;
        }
        else {
          clearInterval(timer);
          assert(tick == 100,                                      //#5
               "Tick accessed via a closure.");
          assert(elem,
               "Element also accessed via a closure.");
          assert(timer,
               "Timer reference also obtained via a closure." );
        }
      }, 10);

    }

    animateIt('box');                                               //#6
    animateIt('box2');                                               //#6

  </script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

Tri*_*ode 8

animateIt('box');                                               //#6
animateIt('box2'); 
Run Code Online (Sandbox Code Playgroud)

一旦第二次调用发生,它将用新值替换计时器值.并且你丢失了对第一个计时器的引用.当它tick到达100时它将仅取消第二个计时器,避开第一个计时器.你可以做一些像下面这样的事情.

var timer = {}, ticks = {};

function animateIt(elementId) {
    var element = document.getElementById(elementId);              //#2
    ticks[elementId] = 0; 
    timer[elementId] = setInterval(function(elementId, element){                         //#4
        //Increase the ticks[elementId]
        //Update the element position
        //While clearing use timer[elementId]
    }, 10);

}
Run Code Online (Sandbox Code Playgroud)