变量偶尔不会产生:最大调用堆栈大小问题

时间:2017-12-28 22:58:02

标签: javascript recursion

错误详细说明了帖子的底部,但在开始之前,我会给出一些背景信息。我有以下脚本,它生成:

1)2& 2之间的两个不同数字20

 var GenerateRandomNumber1to20No1 = GenerateRandomNumber1to20No1(); 
$('.GenerateRandomNumber1to20No1').html(GenerateRandomNumber1to20No1);

 function GenerateRandomNumber1to20No2() {
    var min = 2, max = 20;
    var random = Math.floor(Math.random() * (max - min + 1)) + min;   
  return (random !== GenerateRandomNumber1to20No1) ? random: GenerateRandomNumber1to20No2();

}

 var GenerateRandomNumber1to20No2 = GenerateRandomNumber1to20No2(); 
$('.GenerateRandomNumber1to20No2').html(GenerateRandomNumber1to20No2);

 function GenerateRandomNumber1to20No3() {
    var min = 2, max = 20;
    var random = Math.floor(Math.random() * (max - min + 1)) + min;   
   return (random !== GenerateRandomNumber1to20No1 && random!==GenerateRandomNumber1to20No2) ? random: GenerateRandomNumber1to20No3();

}

2)两个不同于前2个数字的数字

function GenerateRandomNumber1to20lessthanNo1() {
    var min = 2, max = GenerateRandomNumber1to20No1-1;
    var random = Math.floor(Math.random() * (max - min + 1)) + 1;   
    return random;

}

 var GenerateRandomNumber1to20lessthanNo1= GenerateRandomNumber1to20lessthanNo1(); 
$('.GenerateRandomNumber1to20lessthanNo1').html(GenerateRandomNumber1to20lessthanNo1);

function GenerateRandomNumber1to20lessthanNo2() {
    var min = 2, max = (GenerateRandomNumber1to20No2 - 1);
    var random = Math.floor(Math.random() * (max - min + 1)) + min;   
  return (random !== GenerateRandomNumber1to20lessthanNo1) ? random: GenerateRandomNumber1to20lessthanNo2();

}

 var GenerateRandomNumber1to20lessthanNo2 = GenerateRandomNumber1to20lessthanNo2(); 
$('.GenerateRandomNumber1to20lessthanNo2').html(GenerateRandomNumber1to20lessthanNo2);

3)2个不同的PRIME编号

    function PrimeNumber1() {
  var PrimeNumber1= ['3', '5', '7', '11'];
    var PrimeNumber1random= PrimeNumber1[Math.floor(Math.random() * PrimeNumber1.length)];
    return PrimeNumber1random;

}

var PrimeNumber1replacer= PrimeNumber1();
 $('.PrimeNumber1replacer').html(PrimeNumber1replacer);

    function PrimeNumber2() {
  var PrimeNumber2= ['3', '5', '7', '11'];
    var PrimeNumber2random= PrimeNumber2[Math.floor(Math.random() * PrimeNumber2.length)];
    return (PrimeNumber2random !== PrimeNumber1replacer) ? PrimeNumber2random: PrimeNumber2();

}

var PrimeNumber2replacer= PrimeNumber2();
 $('.PrimeNumber2replacer').html(PrimeNumber2replacer);

我使用这些变量替换具有相应变量值的相应类别的元素

<span class = "GenerateRandomNumber1to20nNo2"></span>
<span class = "GenerateRandomNumber1to20nNo2"></span>
<span class = "GenerateRandomNumber1to20lessthanNo1"></span>
<span class = "GenerateRandomNumber1to20lessthanNo2"></span>
<span class = "PrimeNumber1replacer"></span>
<span class = "PrimeNumber2replacer"></span>

有时,代码工作正常:变量生成,元素被这些变量替换。其他时候,变量不会填充,我得到以下两个错误之一:

Uncaught RangeError: Maximum call stack size exceeded
    at GenerateRandomNumber1to20lessthanNo2 *[or No1]*

OR

Uncaught TypeError: PrimeNumber2 *[or 1]* is not a function
    at PrimeNumber2

我试图对Stackoverflow进行一些研究,看起来这可能是递归问题,但我不知道如何解决这个问题。如果有人有任何建议,我将不胜感激。

谢谢!

1 个答案:

答案 0 :(得分:1)

你得到一个堆栈溢出,因为几乎没有一个JS引擎是ES6兼容的,所以即使你使用尾递归你也要吹掉堆栈。现在最好的事情是将它重写为一个循环,直到你成功为止。

function generateRandomNumber(predicate = v => true) {
    const min = 2;
    const max = 20;
    let random;
    do {
        random = Math.floor(Math.random() * (max - min + 1)) + 1;
    } while (!predicate(random));
    return random;
}

// two different numbers
const first1 = generateRandomNumber();
const second1 = generateRandomNumber(v => v !== first1);

// two different number less than previous
const first2 = generateRandomNumber();
const second2 = generateRandomNumber(v => v < first2); // possible infinite loop

// two different prime numbers
function isPrime(n) {
  if (n % 2 === 0) return n == 2
  const limit = Math.sqrt(n);
  for (let i = 3; i <= limit; i += 2) {
    if (n % i === 0)
      return false;
  }
  return true;
}

const first3 = generateRandomNumber(isPrime);
const second3 = generateRandomNumber(v => isPrime(v) && v !== first3);

我遗漏了将值放到DOM上的代码,因为它不是很有趣。我没有在函数之后命名变量,因为它们共享相同的命名空间,因此在设置名称GenerateRandomNumber1to20No1之后,函数已被替换为值。

请注意,我提到“两个不同于之前的数字”,你可能会得到一个无限循环。第一个随机数为2的可能性为5.5%。同一函数生成的数字不小于2,因此不会终止。