Javascript 递归改进

标签 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>
  • 使计数和元素全局化
  • 切换到文本输入而不是 div
  • 将更新 UI 移至设置回调后

最佳答案

不要使用 .innerHTML = ... 来显示数字。根据this test , 设置输入元素的 value 属性效率更高。

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

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

  • setTimeout("countToFiveBillion()",1) 换成 setTimeout(countToFiveBillion,0)。 解释:"countToFiveBillion()" 效率低下;首先,字符串被转换为一个函数并被调用,然后是另一个函数调用。建议的函数运行只需调用一个函数,无需创建新函数。也叫瞬间快。
  • 解除限制(我能够将 18701 增加到 20000)。将限制提升到这样一个四舍五入的数字后,我注意到 counter 值在每次超时之间更新。
  • 修复了实现中的一些错误(将 else block 中的 .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>

fiddle :http://jsfiddle.net/KTtae/

关于Javascript 递归改进,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8185931/

相关文章:

javascript - Pyramid json View ajax调用

JavaScript 改变文本颜色

Java - 此递归中的操作顺序是什么?

C 子文件夹的递归目录副本

javascript - JavaScript 尾调用中的函数是否经过优化?

c++ - 用递归减去反向数字

javascript - Discord bot清除命令错误[INVALID_TYPE] : Supplied options is not an object

javascript - 如何使 map 开启器显示全高?

c# - 重载时无限递归==

javascript - 确定 LI 是否溢出的函数