Generate random string/characters in JavaScript
Generate random string/characters in JavaScript
Question
I want a 5 character string composed of characters picked randomly from the set [azAZ09]
.
What's the best way to do this with JavaScript?
Accepted Answer
I think this will work for you:
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
console.log(makeid(5));
Popular Answer
let r = Math.random().toString(36).substring(7);
console.log("random", r);
Note: The above algorithm has the following weaknesses:
 It will generate anywhere between 0 and 6 characters due to the fact that trailing zeros get removed when stringifying floating points.
 It depends deeply on the algorithm used to stringify floating point numbers, which is horrifically complex. (See the paper "How to Print FloatingPoint Numbers Accurately".)
Math.random()
may produce predictable ("randomlooking" but not really random) output depending on the implementation. The resulting string is not suitable when you need to guarantee uniqueness or unpredictability. Even if it produced 6 uniformly random, unpredictable characters, you can expect to see a duplicate after generating only about 50,000 strings, due to the birthday paradox. (sqrt(36^6) = 46656)
Read more... Read less...
Math.random is bad for this kind of thing
Option 1
If you're able to do this serverside, just use the crypto module 
var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');
// "bb5dc8842ca31d4603d6aa11448d1654"
The resulting string will be twice as long as the random bytes you generate; each byte encoded to hex is 2 characters. 20 bytes will be 40 characters of hex.
Option 2
If you have to do this clientside, perhaps try the uuid module 
var uuid = require("uuid");
var id = uuid.v4();
// "110ec58aa0f24ac48393c866d813b8d1"
Option 3
If you have to do this clientside and you don't have to support old browsers, you can do it without dependencies 
// dec2hex :: Integer > String
// i.e. 0255 > '00''ff'
function dec2hex (dec) {
return dec < 10
? '0' + String(dec)
: dec.toString(16)
}
// generateId :: Integer > String
function generateId (len) {
var arr = new Uint8Array((len  40) / 2)
window.crypto.getRandomValues(arr)
return Array.from(arr, dec2hex).join('')
}
console.log(generateId())
// "82defcf324571e70b0521d79cce2bf3fffccd69"
console.log(generateId(20))
// "c1a050a4cd1556948d41"
For more information on crypto.getRandomValues

The
crypto.getRandomValues()
method lets you get cryptographically strong random values. The array given as the parameter is filled with random numbers (random in its cryptographic meaning).
Here's a little console example 
> var arr = new Uint8Array(4) # make array of 4 bytes (values 0255)
> arr
Uint8Array(4) [ 0, 0, 0, 0 ]
> window.crypto
Crypto { subtle: SubtleCrypto }
> window.crypto.getRandomValues()
TypeError: Crypto.getRandomValues requires at least 1 argument, but only 0 were passed
> window.crypto.getRandomValues(arr)
Uint8Array(4) [ 235, 229, 94, 228 ]
For IE11 support you can use 
(window.crypto  window.msCrypto).getRandomValues(arr)
For browser coverage see https://caniuse.com/#feat=getrandomvalues
Short, easy and reliable
Returns exactly 5 random characters, as opposed to some of the top rated answers found here.
Math.random().toString(36).substr(2, 5);
Here's an improvement on doubletap's excellent answer. The original has two drawbacks which are addressed here:
First, as others have mentioned, it has a small probability of producing short strings or even an empty string (if the random number is 0), which may break your application. Here is a solution:
(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
Second, both the original and the solution above limit the string size N to 16 characters. The following will return a string of size N for any N (but note that using N > 16 will not increase the randomness or decrease the probability of collisions):
Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
Explanation:
 Pick a random number in the range [0,1), i.e. between 0 (inclusive) and 1 (exclusive).
 Convert the number to a base36 string, i.e. using characters 09 and az.
 Pad with zeros (solves the first issue).
 Slice off the leading '0.' prefix and extra padding zeros.
 Repeat the string enough times to have at least N characters in it (by Joining empty strings with the shorter random string used as the delimiter).
 Slice exactly N characters from the string.
Further thoughts:
 This solution does not use uppercase letters, but in almost all cases (no pun intended) it does not matter.
 The maximum string length at N = 16 in the original answer is measured in Chrome. In Firefox it's N = 11. But as explained, the second solution is about supporting any requested string length, not about adding randomness, so it doesn't make much of a difference.
 All returned strings have an equal probability of being returned, at least as far as the results returned by Math.random() are evenly distributed (this is not cryptographicstrength randomness, in any case).
 Not all possible strings of size N may be returned. In the second solution this is obvious (since the smaller string is simply being duplicated), but also in the original answer this is true since in the conversion to base36 the last few bits may not be part of the original random bits. Specifically, if you look at the result of Math.random().toString(36), you'll notice the last character is not evenly distributed. Again, in almost all cases it does not matter, but we slice the final string from the beginning rather than the end of the random string so that short strings (e.g. N=1) aren't affected.
Update:
Here are a couple other functionalstyle oneliners I came up with. They differ from the solution above in that:
 They use an explicit arbitrary alphabet (more generic, and suitable to the original question which asked for both uppercase and lowercase letters).
 All strings of length N have an equal probability of being returned (i.e. strings contain no repetitions).
 They are based on a map function, rather than the toString(36) trick, which makes them more straightforward and easy to understand.
So, say your alphabet of choice is
var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Then these two are equivalent to each other, so you can pick whichever is more intuitive to you:
Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
and
Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
Edit:
I seems like qubyte and Martijn de Milliano came up with solutions similar to the latter (kudos!), which I somehow missed. Since they don't look as short at a glance, I'll leave it here anyway in case someone really wants a oneliner :)
Also, replaced 'new Array' with 'Array' in all solutions to shave off a few more bytes.
The most compact solution, because slice
is shorter than substring
. Subtracting from the end of the string allows to avoid floating point symbol generated by the random
function:
Math.random().toString(36).slice(5);
or even
(+new Date).toString(36).slice(5);
Update: Added one more approach using btoa
method:
btoa(Math.random()).slice(0, 5);
btoa(+new Date).slice(7, 2);
btoa(+new Date).substr(7, 5);
// Using Math.random and Base 36:
console.log(Math.random().toString(36).slice(5));
// Using new Date and Base 36:
console.log((+new Date).toString(36).slice(5));
// Using Math.random and Base 64 (btoa):
console.log(btoa(Math.random()).slice(0, 5));
// Using new Date and Base 64 (btoa):
console.log(btoa(+new Date).slice(7, 2));
console.log(btoa(+new Date).substr(7, 5));
Something like this should work
function randomString(len, charSet) {
charSet = charSet  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var randomString = '';
for (var i = 0; i < len; i++) {
var randomPoz = Math.floor(Math.random() * charSet.length);
randomString += charSet.substring(randomPoz,randomPoz+1);
}
return randomString;
}
Call with default charset [azAZ09] or send in your own:
var randomValue = randomString(5);
var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');