Why not allowing an argument to Math.random()
so that instead of having to do 10000 * Math.random()
we can simply do Math.random(10000)
?
Saving one character is a pretty small benefit to adding complexity to an API.
Given how widely confusing it is for most JS developers to use Math.random
, especially juniors, my general sentiment would be to support for this, but I could see this becoming a slippery slope very quickly.
What if you want to offset the start and end value and how many decimal points you want to include. Next thing you know, you're using this syntaxβ¦
Math.random = function(max = 1, min = 0, precision = Infinity) {
// function logic here...
}
β¦and everybody is more confused than they were using Math.random
in its current implementation.
As much as I'd love to see this function made simpler to use, it's hard to imagine a use case that's simpler for all use cases than what's already in place. Instead, I'd opt for a helper function you can expose globally in your codebase, like this:
function getRandomInt(a = 1, b) {
const [min, max] = (b === undefined ? [0, a] : [a, b]).sort((a, b) => a - b);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
This covers several use cases:
-
No args: By default, this helper function returns a boolean-ish number (
1
(truthy) or0
(falsy)), which could be considered a feature in itself. This way, you could do something likeBoolean(getRandomInt())
to get a random boolean, or maybe even wrap that in another helper function likegetRandomBool
.Example:
getRandomInt() // 0 | 1
Example:Boolean(getRandomInt()) // true | false
-
1 arg: With a single arg, that arg stands as the max when positive or min when negative, with the opposite value (min or max) defaulting to 0.
Example:
getRandomInt(10) // 0-10, inclusive
-
2 args: When using both args, the args represent both the min and max values and auto-sort numerically in case the min is higher than the max.
Example:
getRandomInt(5, 10) // 5-10, inclusive
getRandomBool
could look like this:
function getRandomBool() {
return Boolean(getRandomInt());
}
What I'd really like to see is a more full-fledged random API for JavaScript. So, you'd have functions like randomInt(start, end)
, randomFloat(start, end)
, randomBoolean()
, maybe you can even have different randomFloat() functions that generate numbers over configurable distributions. The ability to seed multiple independent generators would be nice as well.
I had started a bit of a discussion around this in the past: A more complete random API?
I think it would be more conventional, something like this
Number.random(start: number = 0, end: number = 1.0) -> number
BigInt.random(start: bigint = 0n, end: bigint = 4294967295n) -> bigint
String.random(start: string = "A", end: string = "z") -> bigint
It's probably not a good idea to modify the Math.random()
signature.
Any existing code containing statement as Math.random()
parameter will change behavior.
This is sometime used to minify code, example:
foo();x=Math.random()
x=Math.random(foo()) // 1 char saved
Otherwise, you can use this minimal function that admit 0, 1 or 2 parameters:
const random = (min = 1, max = 0) => (max - min) * Math.random() + min
I hope automatic minifiers aren't doing this. Maybe code-golfers are.
I've heard it said around that adding new parameters to existing functions is not considered a breaking change, unless there's evidence of actual websites doing it. And, indeed, we often see proposals updating function signatures of existing functions to support new parameters.
I have a javascript utility file that grows slowly everytime i work with javascript and implementing various forms of randomness is something i've found myself doing. i found it much better to make a custom random function
function random () : Number;
random.int (max : Number) : Number;
random.int (min : Number, max : Number) : Number;
random.choose (array : Array) : var;
random.weighted (weight : Number) : Number;
and so on...
Not only minifiers, you can imagine someone write const randomNumbers = Array.from({length:10}).map(Math.random)
.
Yes, I can imagine that.
My understanding is that tc39 is still (currently) ok with adding new parameters to existing functions, despite that risk. And if they find out it's web incompatible because people were doing that sort of thing, they'd go back and redesign the proposal.
This is why I try to avoid doing that in my own code, even though it looks nice - because I don't want to be part of the reason tc39 can't add a new parameter to an existing function.