Javascript递归改进

时间:2011-11-18 16:52:36

标签: 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>

无论如何,它并没有在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>

这只会在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>
  • Made count and element globabl
  • 切换到文本输入而不是div
  • 在设置回调后将更新UI移至

2 个答案:

答案 0 :(得分:2)

请勿使用.innerHTML = ...来显示号码。根据{{​​3}},设置输入元素的value属性更有效。

<input type="text" id="counter" value="0" />

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

  • setTimeout("countToFiveBillion()",1)交换setTimeout(countToFiveBillion,0)。 说明:"countToFiveBillion()"效率低下;首先,字符串转换为函数并调用,然后是另一个函数调用。建议的函数运行只需调用函数,而不创建新的函数。它也被称为快一秒。
  • 提升限制(我能够将18701增加到20000)。将限制提升到这样的舍入数后,我注意到counter值在每次超时之间都会更新。
  • 修正了实施中的一些错误(在{ - 1}}处替换了.innerHTML

相关代码:

.value

小提琴:this test

答案 1 :(得分:0)

Webworker示例,index.html

<!DOCTYPE HTML>
<html>
<head>
    <title>5 billion</title>
</head>
<body>
    <input type="text" id="counter" value="0" />
    <script type="text/javascript" charset="utf-8">
        var 
            iCounter = document.getElementById('counter')
            , counter = new Worker('worker.js');

        iCounter.value = 0;
        counter.addEventListener('message', function (e) {
            iCounter.value = e.data;
        }, false);
    </script>
</body>
</html>

worker.js:

for (var i = 0; i < 5e9; i++) {
    if (i % 18701 === 0) {
        postMessage(i);
    }
}

如果需要,计数可以分成多个工人。