2011-11-18 33 views
10
iş yerinde

Birisi şaka Neyse o Chrome ve bir konuşma bunun büyük bir iş yapmazJavaScript Özyineleme İyileştirme

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

şuydu tarayıcınızı çökmesine tasarlanmış bir HTML dosyası bir e-posta gönderdi tarayıcının yanıt vermemesine veya çökmesine neden olmadan, mümkün olduğunca hızlı bir şekilde 5.000.000.000 sayfaya ulaşması için kimin javascript yazabileceğini görmek için arkadaşça bir yarışma yarattı.

Chrome'da kullanılmak üzere tasarlanmıştır javascript aşağıdaki parça ile geldi.

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

bu sadece krom aday olacağını nedeni krom bir stackoverflow yaratmaktan kaçınmak için setTimeout çağrısı kullanarak olmam. (Ayrıca Chrome, tüm tarayıcılardan en çok çağıran aramalara olanak sağlar).

bana bu herhangi çabuk sayımı yapmak için herhangi bir yolu var mı? Bir taşmaya neden olan miktarın biraz artabileceğine inanıyorum (100'den az olsa bile) Tek şart, mümkün olduğu kadar çok sayıyı göstermesi gerektiğidir.


Geliştirilmiş Kod:

<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> 
  • Yapılan sayım ve eleman globabl
  • geri arama

cevap

2
ayarladıktan sonra güncelleme UI taşındı yerine div girişini metne geçildi

.innerHTML = ...'u kullanmayın numarayı göster. this test'a göre, bir giriş öğesinin value özelliğini ayarlamak daha verimlidir. Bunun yerine yeni bir fonksiyon inşa etmenin

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

, ben küresel/yerel değişkenler kullanmak için tavsiye ve setTimeout bir argüman olarak bir işlev başvuru ileterek veya init en setInterval kullanın.

  • setTimeout(countToFiveBillion,0) için setTimeout("countToFiveBillion()",1)'u değiştirin. Açıklama: "countToFiveBillion()" verimsiz; İlk olarak, dize bir işleve dönüştürülür ve çağrılır, sonra başka bir işlev çağrısı izler. Önerilen işlev sadece yeni bir işlev oluşturmadan bir işlevi çağırmak için çalışır. Ayrıca ikinci bir daha hızlı bölünmüş denir. sınırı kaldırın
  • (I 20000 18701 artırarak). Sınırı böyle bir yuvarlak sayıya yükselttikten sonra, counter değerinin her zaman aşımı arasında güncellendiğini fark ettim.
  • uygulanmasında bazı hatalar düzeltildi (başka blokuna .value ile .innerHTML değiştirilir).

ilgili kod:

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

Fiddle: http://jsfiddle.net/KTtae/

+0

JS woudl'da bir işlevin nasıl referans olarak geçeceğinden tam olarak emin değilim Sadece şu anda yaptığım gibi this.countToFiveBillion yapmak yerine? – msarchet

+0

Küresel olarak değişkenleri bildirin, ardından setTimeout (countToFiveBillion, 1) 'ile setTimeout (..)' değiştirin. –

+0

Ah evet, mantıklı geliyor – msarchet

0

WebWorker örneğin,

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

Gerekirse sayma, birden çok işçiye bölünebilir.