在for循环中使用数组作为参数的setTimeout行为异常

时间:2018-09-02 04:28:15

标签: javascript settimeout

我一直在开发第二款游戏,其工作方式如下:

  • 有一个按钮,其位置每x秒随机变化
  • x秒由setTimeout
  • 控制
  • 每当用户单击按钮时,他们的分数就会增加10
  • 当得分达到30时,startGame会调用Initialize,这会使用JavaScript创建一个新按钮,并将该按钮推入名为numOfBox的数组中。
  • 控件使用更新后的startGame返回到numOfBox,该控件现在具有两个按钮,并且每x秒更改一次顶部/左侧坐标

setTimeout每x秒多次调用该函数,而不是每x秒一次。如何每x秒仅一次调用该函数?

var box=document.getElementById('boxId');
var main=document.getElementById('Maincont');
var timeout=[];
var cnt=0;
var scr=0;
var levelCnt=30;
var divcnt=0;
var numOfbox=[];
var fcnt=0;
function createDiv(Name,Width,Height,Background,Margin,Padding) {
    var t=t+divcnt;
    divcnt+=1;
    var Name=Name+divcnt;
    var Nameid='boxId'+divcnt;
    Name=document.createElement('button');
    Name.id=Nameid;
    console.log('IN CREATEDIV :-'+ Nameid+':::'+Name+' cnt '+ cnt);
    Name.style.width=Width;
    Name.style.height=Height;
    Name.style.background=Background;
    Name.style.margin=Margin;
    Name.style.padding=Padding;
    Name.style.boxSizing='border-box';
    Name.style.position='absolute';
    Name.style.top='10px';
    Name.style.left='10px';
    Name.style.color='white';
    Name.style.textAlign='center';
    Name.style.fontSize='15px';
    Name.style.textDecoration='none';
    Name.style.cursor='pointer';
    Name.disabled=true;
    t=document.createTextNode('HIT ME');
    Name.appendChild(t);
    Name.addEventListener('click', function() {
        this.style.background='black';
        scr+=10;
        cnt+=10;
        this.innerHTML= 'SCORE = ' +String(scr);
    });
    var b=document.getElementById('Maincont');
    // FIRST HIT ME BOX IS READY NOW....
    b.appendChild(Name);
    // Array numOfbox loaded with all the Box id's.
    numOfbox.push(Name.id);

    console.log('PUSHING DIV:-'+ Name.id + " IN ARRAY :=" +numOfbox);
    // creatediv is called when score is scr%30==0. 
    if (numOfbox.length > 1) {
        return Name.id;
    }
}

function Initialize() {
    if (main.childNodes.length < 5) {
        if ((cnt > 0) && (cnt %30 ==0)) {
            var id='targetCont'+divcnt;
            divcnt+=1;
            boxId=createDiv(id,'130px','50px','black','0px','0px');
            console.log('Inside Initialize:-'+id+' cnt '+ cnt);
            cnt=0;
        }
        startGame();
    }
}

function startGame() {
    var d=new Date();
    var t=d.getMinutes()+':'+d.getSeconds();
    fcnt+=1;
    console.log('TIME IS:-'+ t + "  cnt:-" +fcnt+' INSIDE STARTGAME:-'+numOfbox+':'+numOfbox.length+ ' CNT'+cnt);
    for (var i=0 ; i < numOfbox.length ; i++) {
        if ((cnt > 0) && (cnt %30 ==0)) {
            Initialize();
        } else {
            console.log('STARTING GAME FOR DIV:='+numOfbox[i]);
            var box=document.getElementById(numOfbox[i]);
            console.log(box);
            box.disabled=false;
            var max=500;
            var min=10;
            var topRand=(Math.floor(Math.random() * (max-min+1) + min));
            var max=1200;
            var min=10;
            var leftRand=(Math.floor(Math.random() * (max-min+1) + min));
            box.style.background='black';
            box.style.top=topRand+'px';
            box.style.left=leftRand+'px';
            console.log('CNT:='+cnt);
            timeout=setTimeout(startGame,10000,numOfbox);
        }
    }
}

function stopGame() {
    clearTimeout(timeout);
    console.log('IN STOPGAME:-'+timeout+' length '+timeout.length);
        for (var i=0 ; i < numOfbox.length ; i++) {
        console.log(timeout[i]);
        clearTimeout(timeout[i]);
        var box=document.getElementById(numOfbox[i]);
        box.style.background='red';
        box.style.top='10px';
        box.style.left='10px';
    }   

    timeout=[]; 
}

我宁愿使用JavaScript而不是ECMA5 / 6或jQuery或使用箭头函数来执行此操作。如果需要,我可以提供其余代码。

1 个答案:

答案 0 :(得分:3)

我注意到您的代码有几个问题。

  1. 您正在循环调用setTimeout。因此,如果您拥有numOfbox.length === 15,则setTimeout将在您设置后10,000毫秒被调用15次。这可能是您看到startGame的电话数量超出您预期的原因吗?

  2. 我看到了变量numOfbox,但是由于没有在startGame函数中声明变量,因此我不得不假定它在父范围内。所以,在你做的那一行

    timeout[i] = setTimeout(startGame, 10000, numOfbox);
    

请注意,由于numOfbox在更高级别的范围内, startGame不带任何参数,因此numOfbox参数(setTimeout中的第三个参数)实际上什么也没用:numOfbox变量实际上的使用来自父作用域。也许可以,但是您应该考虑这里发生的事情。