I am trying to add some code where the user clicks a button and the code generates 3 numbers (none repeating, so 245 is OK but 122 and 121 is not) and display them onscreen, one each second. To ensure there are no repeats, I am using an array: var usedNums = [];
. Then, I create the number ( digit = Math.random()
) and check if it is already in the array, and if it's not, add it, like this:
if ($.inArray(digit, usedNums) !== -1) {
newNums();
} else {
usedNums.push(digit);
$('#memDigit').html(digit);
}
The first few times, it works, but when I click it for the 10th time, I get the Uncaught RangeError: Maximum call stack size exceeded
error. Help!
Here's the full code:
var usedNums = [];
var digit;
var amount = 3;
function newNums() {
digit = Math.floor(Math.random() * 10);
if ($.inArray(digit, usedNums) !== -1) {
newNums();
} else {
usedNums.push(digit);
$('#memDigit').html(digit);
}
}
function createNums() {
for (var i; i < amount; i++) {
setTimeout(newNums, 1000);
}
}
//$(document).ready(createNums);
我认为您应该在每个数字生成完成后清空/重新初始化usedNums数组。
If IE <= 10 is not a concern, you may want to take advantage of crypto.getRandomValues
to do this in one shot instead.
The getRandomValues
method fills a TypedArray
with a series of random values in the range supported by that array type. If we ask for 10 of these vales, we now have, in effect, a hash of the numbers 0-9 (that is, the indices of the array) pre-associated with random values for sorting by (the values). The result will be both more random and — unlike the 'already seen this value, try again' pattern — it should run in constant time.
ES6:
const nums = [ ...crypto.getRandomValues(new Int16Array(10)) ]
.map((sortVal, num) => [ sortVal, num ])
.sort(([ a ], [ b ]) => a < b ? -1 : Number(a > b))
.map(([ , num ]) => num)
.slice(0, 3);
ES5:
var nums = [].slice.call(crypto.getRandomValues(new Int16Array(10)))
.map(function(sortVal, num) { return [ sortVal, num ]; })
.sort(function(a, b) { return a[0] < b[0] ? -1 : Number(a[0] > b[0]); })
.map(function(pair) { return pair[1]; })
.slice(0, 3);
Breakdown:
new Int16Array(10)
creates an empty TypedArray of length 10 crypto.getRandomValues(...)
fills that array with random values sort
implementation bug)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.