2011-11-18 61 views
10

有人在工作中開玩笑地發出了一封電子郵件,意在崩潰的瀏覽器,這是下面的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來設置回調

回答

2

請勿使用.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

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

如果需要,計數可以分成多個工人。