setTimeout可以与闭包内的函数一起使用吗?

时间:2015-04-09 15:01:35

标签: javascript

JavaScript的setTimeout函数可以与闭包内的函数一起使用吗?如果对setTimeout的调用是在同一个闭包内进行的,该怎么办?

有了我的尝试,看来你做不到。不过,我不确定我是否遗漏了任何东西。

基本上,我想这样做:

var ButtonCycler = (function() {
  var ButtonCycler = {};
  var autoCycle;
  var idx = 0;
  var buttonIds = [];
  buttonIds[0] = "id1";
  buttonIds[1] = "id2";
  //"Public" methods
  ButtonCycler.startAutoCycle = function() {
    autoCycle = true;
    cycleButtons();
  }
  ButtonCycler.stopAutoCycle = function() {
    autoCycle = false;
  }
  //Worker function (effectively private because it's in the closure)
  function cycleButtons() {
    var radioButton;
    if(autoCycle) {
      radioButton = document.getElementById(buttonIds[idx]);
      radioButton.checked = true;
      idx++;
      if(idx >= buttonIds.length) {
        idx = 0;  //Start over at first button
      }
      setTimeout('cycleButtons()',2500); //Delay for 2.5 seconds
    }
  }
  return ButtonCycler;
})(); //IIFE

然后在onload页面中,我可以这样做:

ButtonCycler.startAutoCycle();

当用户手动点击其中一个单选按钮时,我可以这样做:

ButtonCycler.stopAutoCycle();

执行循环的机制可以很好地封装在闭包中。

当我尝试这个时,我收到cycleButtons不存在的错误。但是,对cycleButtons的初始调用成功了。这是由setTimeout调用启动的调用失败。

2 个答案:

答案 0 :(得分:5)

您将cycleButtons()作为字符串传递,稍后将使用eval调用该字符串。这将假设cycleButtons在全局范围内可用(它不是)。相反,将引用传递给实际函数:

setTimeout(cycleButtons, 2500);

答案 1 :(得分:0)

你的setTimeout不正确,你应该使用clearTimeout来简化你的代码。以下是如何简化它的示例:

var ButtonCycler = (function () {
    var ButtonCycler = {};
    var autoCycle;
    var idx = 0;
    var buttonIds = [];
    var timer;
    buttonIds[0] = "id1";
    buttonIds[1] = "id2";
    //"Public" methods
    ButtonCycler.startAutoCycle = function () {
        cycleButtons();
    }
    ButtonCycler.stopAutoCycle = function () {
        clearTimeout(timer);
    }
    //Worker function (effectively private because it's in the closure)
    function cycleButtons() {
        var radioButton;
        radioButton = document.getElementById(buttonIds[idx]);
        radioButton.checked = true;
        idx = (idx < buttonIds.length - 1) ? idx + 1 : 0;

        timer = setTimeout(function () {
            cycleButtons();
        }, 2500); //Delay for 2.5 seconds      
    }
    return ButtonCycler;
})(); //IIFE