Javascript递归改进

msa*_*het 10 javascript recursion

工作中的某个人开玩笑地发了一封带有html文件的电子邮件,意图使你的浏览器崩溃,如下所示

<html>
<script type="text/javascript">
function crash(){
  for(i=0;i<5000000001;i++){
    document.write(i);
  }
}
</script>
<body onload="crash();">
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

无论如何,它并没有在Chrome中做得很好,并且谈话产生了一个友好的竞争,看看谁可以编写javascript以尽可能快地使页数达到5,000,000,000而不会导致浏览器无响应或崩溃.

我想出了以下用于Chrome的javascript.

<html>
<script type="text/javascript">
function countToFiveBillion(counter, num){
  if(num < 5000000000)
  {
    num++;
    if(num % 18700 == 0){
      counter.innerHTML = num;
      setTimeout(function() {countToFiveBillion(counter, num)}, 1);
    } else {
      countToFiveBillion(counter, num);
    }
  }
}
function initiateCountDown()
{
   var counter = document.getElementById("counter");
   var num = +counter.innerHTML;
   countToFiveBillion(counter, num);
}
</script>
<body onload="initiateCountDown();">
<div id="counter">0</div>
</body>

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

这只会在chrome中运行的原因是我正在使用setTimeout调用来避免在chrome中创建stackoverflow.(Chrome还允许您在所有浏览器中进行递归调用的最大堆栈).

我有什么方法可以更快地计算这个数字吗?我认为我可以在导致溢出之前稍微增加一点数量(虽然小于100)但唯一的规定是必须显示尽可能多的数字.


改进代码:

<html>
<script type="text/javascript">
var counter;
var num = 0;
function countToFiveBillion(){
    if(num < 5000000000)
    {
    num++;
    if(num % 18701 == 0){
        setTimeout("countToFiveBillion()", 1);
            counter.value = num;
        } else {
        countToFiveBillion();
    }
    } else {
        counter.value = "number greater than 5 Billion";
    }
}
function initiateCountDown()
{
   counter = document.getElementById('counter');
   countToFiveBillion();
}
</script>
<body onload="initiateCountDown();">
    <input type="text" id="counter" value="0" />
</body>

</html>
Run Code Online (Sandbox Code Playgroud)
  • 制作计数和元素globabl
  • 切换到文本输入而不是div
  • 在设置回调后将更新UI移动到

Rob*_*b W 2

不要用来.innerHTML = ...显示号码。根据此测试,设置value输入元素的属性更加有效。

<input type="text" id="counter" value="0" />
Run Code Online (Sandbox Code Playgroud)

我建议使用全局/局部变量,并将函数引用作为参数传递给setTimeoutsetInterval在 init 处使用,而不是构造新函数。

  • 交换setTimeout("countToFiveBillion()",1)setTimeout(countToFiveBillion,0). 解释:"countToFiveBillion()"效率低下;首先,字符串被转换为函数并被调用,然后另一个函数调用随之而来。建议的函数运行只需调用一个函数,而无需创建新函数。它也被称为瞬间更快。
  • 解除限制(我能够将 18701 增加到 20000)。将限制提升到这样一个四舍五入的数字后,我注意到该counter值在每次超时之间都会更新。
  • 修复了实现中的一些错误(替换.innerHTML.valueelse 块)。

相关代码:

<input type="text" id="counter" />
<script>
var counter, num = 0;
function countToFiveBillion(){
    if(num < 5e9)
    {
        if(++num % 18701 == 0){
            setTimeout(countToFiveBillion, 0);
            counter.value = num;
        } else {
            countToFiveBillion();
        }
    } else {
        counter.value = "number greater than 5 Billion";
    }
}
function initiateCountDown(){
    counter = document.getElementById('counter');
    counter.value = num; //Init, show that the script is 
    countToFiveBillion();
}
window.onload = initiateCountDown;
</script>
Run Code Online (Sandbox Code Playgroud)

小提琴: http: //jsfiddle.net/KTTae/