的Javascript递归改进

问题描述:

有人在工作中开玩笑地发出了一封电子邮件,意在崩溃的浏览器,这是下面的Javascript递归改进

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

一个HTML文件,反正它不会在Chrome和谈话做一个伟大的工作它引发了一场友好的竞赛,看看谁能够尽可能快地编写javascript来使页数达到50亿,而不会导致浏览器无响应或崩溃。

我想出了下面的一段JavaScript代码是意在Chrome浏览器中使用。

<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中创建一个计算器。 (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> 
  • 制造数和元素globabl
  • 切换到文本而不是DIV输入
  • 移动更新UI来设置回调

请勿使用.innerHTML = ...显示号码。据this test,设置一个输入元件的value属性是更有效的。

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

如果不建立新的功能,我建议使用全局/局部变量,并通过一个函数引用作为参数传递给setTimeout,或者在初始化使用setInterval

  • setTimeout(countToFiveBillion,0)交换setTimeout("countToFiveBillion()",1)。 说明:"countToFiveBillion()"效率低下;首先,字符串被转换为一个函数并被调用,然后是另一个函数调用。建议的函数运行只需要调用一个函数,而不需要创建新函数。它也被称为更快的一秒。
  • 提起极限(我是能够增加18701至20000)。解除限制后,我注意到counter值在每次超时之间更新。
  • 固定在执行一些错误(在else区块取代.innerHTML.value)。

相关的代码:

<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> 

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

+0

我不完全知道如何传递一个函数在JS参考woudl我只是做的,而不是我目前做的方式this.countToFiveBillion? – msarchet

+0

全局声明变量,然后更换'的setTimeout(..)''通过的setTimeout(countToFiveBillion,1)'。 –

+0

是啊,有道理 – msarchet

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); 
    } 
} 

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