2013-02-01 20 views
1

有在下面的代码的错误:索引超出范围的bug在我的JavaScript代码

generate: function() { 
    var generated = []; 
    for (var j = 0; j < objectDefinitions.length; j++) { 
     var randomNumber; 

     if (!objectDefinitions[j].restrictGeneration) { 
      continue; 
     } 

     randomNumber = Math.random(); 

     if (randomNumber < objectDefinitions[j].probability) { 
      generated.push(objectDefinitions[j].createObject()); 
      objectDefinitions[j].restrictGeneration = true; 
      if (j > 5) { 
      } 
      setTimeout(function() {     
       //console.log(j); 
       objectDefinitions[j].restrictGeneration = false; 
      }, objectDefinitions[j].cooldown); 
     } 
    } 
    return generated; 
} 

当setTimeout的“火”的变量j为6,这将导致一个数组索引超出范围的异常,因为的阵列中只有6个项目。我真的不明白发生了什么事,我在setTimeout之外检查了j,它从不是6,但它在声明后似乎发生了变化。谢谢你的帮助。

+0

我不知道是否有这个问题,一个更好的标题,因为这似乎是新手JS程序员一个很好的学习机会,这个问题应该被发现! –

回答

1

它读取的变量j是您在循环中使用的变量,因此它不会被“复制”。

setTimeout(
    (function(k){ 
     return function() {    
      objectDefinitions[k].restrictGeneration = false; 
     }; 
    }(j)) 
, objectDefinitions[j].cooldown); 

jk变量复制这种方式。但是每循环迭代有一个k变量。

+0

非常感谢,我需要咀嚼一下,但代码正常工作 – HedgepigMatt

0

你的空if语句执行(什么都不做),然后将其移动到设置超时,其中j仍大于5

基本上,你应该退出在这一点上,而不是在继续执行更多的代码在if语句之后,或者在那里做一个else语句,以便如果j> 5,则不执行进一步的代码。

+0

感谢您的回复,遗憾的是,j从来没有> 5。这是奇怪的事情。 – HedgepigMatt

0

这是由于关闭

您看到的值为6,因为j++是最后一次触发for循环的退出。因此,关闭现在有一个j 6.当setTimeout执行(这是for循环完成后,它在封闭的上下文中执行。

你需要这个代码转移到自己的封闭,其中,通过移动它到它自己的功能做喜欢的东西:。

generate: function() { 
    var generated = []; 
    for (var j = 0; j < objectDefinitions.length; j++) 
    { 
     handleIteration(generated, j); // Re-factor your code into a new function 
    } 

    return generated; 
} 
+0

是的,我确实认为这可能与范围/封闭有关,但由于某种原因,我对于发生了什么感到困惑,我(错误地)认为j会被复制而不是引用。我通过使用xavierm02所描述的匿名函数解决了这个问题,使用单独的函数可能更优雅,尽管如此谢谢。 – HedgepigMatt

+0

是的,xavierm02的回答是一个很好的解决方案! –