为什么javascript会不断递归

为什么javascript会不断递归,javascript,closures,Javascript,Closures,我正在阅读清单5.6中javascript忍者的秘密。在解释中,作者要求将变量移动到全局范围。然后,创建另一个id,即box2,并在box1上设置动画之后调用box2上的动画,以显示闭包为变量提供的保护。我理解这个概念,但我得到的结果是断言语句的无限递归。我不明白 为什么会发生这种情况?为什么它会进入无限递归循环 代码如下 谢谢 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <

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

为什么会发生这种情况?为什么它会进入无限递归循环

代码如下

谢谢

<!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>

清单5.6
#框{
位置:绝对位置;
边框:3件纯蓝;
宽度:200px;高度:200px;
背景色:#6495ed;
字号:2em;
}
ボックス                               
ボックス                               
var-elem;
变种蜱;
无功定时器;
函数animateIt(elementId){
elem=document.getElementById(elementId);/#2
勾选=0;/#3
计时器=设置间隔(函数(){/#4
如果(勾选<100){
elem.style.left=elem.style.top=tick+“px”;
tick++;
}
否则{
清除间隔(计时器);
断言(勾号=100,/#5
“通过闭包访问勾号。”);
断言(元素),
“元素也可以通过闭包访问。”);
断言(计时器,
“计时器参考也通过闭包获得。”);
}
}, 10);
}
animateIt('box')//#6.
animateIt('box2')//#6.
一旦发生第二次调用,它将用新值替换计时器值。并且您丢失了对第一个计时器的引用。因此,当
勾选
达到
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);

}

因为您已经在全局状态下定义了变量,所以它们会发生变化,而您在setInterval回调函数中使用了它们,但是如果您想这样使用它,则应该使用闭包:

function animateIt(elementId) {

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

    var callback = (function (elem, tick) {
        return function () {
            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.");
            }
        };
    })(elem);

    timer = setInterval(callback, 10);

}
函数animateIt(elementId){
elem=document.getElementById(elementId);/#2
勾选=0;/#3
var callback=(函数(elem,tick){
返回函数(){
如果(勾选<100){
elem.style.left=elem.style.top=tick+“px”;
tick++;
}否则{
清除间隔(计时器);
断言(勾号=100,/#5
“通过闭包访问勾号。”);
断言(元素),
“元素也可以通过闭包访问。”);
断言(计时器,
“计时器参考也通过闭包获得。”);
}
};
})(elem);
定时器=设置间隔(回调,10);
}
function animateIt(elementId) {

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

    var callback = (function (elem, tick) {
        return function () {
            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.");
            }
        };
    })(elem);

    timer = setInterval(callback, 10);

}