¿Cadena alfanumérica aleatoria en JavaScript?
¿Cuál es la forma más corta (dentro de lo razonable) de generar una cadena alfanumérica aleatoria (mayúsculas, minúsculas y números) en JavaScript para usarla como un identificador probablemente único?
Me pareció una solución realmente agradable y elegante:
Math.random().toString(36).slice(2)
Notas sobre esta implementación:
- Esto producirá una cadena de entre cero y 12 caracteres de largo, generalmente 11 caracteres, debido al hecho de que la cadena de punto flotante elimina los ceros finales.
- No generará letras mayúsculas, sólo minúsculas y números.
- Debido a que la aleatoriedad proviene de
Math.random()
, el resultado puede ser predecible y, por lo tanto, no necesariamente único. - Incluso suponiendo una implementación ideal, la salida tiene como máximo 52 bits de entropía, lo que significa que puede esperar un duplicado después de generar alrededor de 70 millones de cadenas.
Si solo quieres permitir caracteres específicos, también puedes hacerlo así:
function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
var rString = randomString(32, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
Aquí hay un jsfiddle para demostrar: http://jsfiddle.net/wSQBx/
Otra forma de hacerlo podría ser utilizar una cadena especial que le indique a la función qué tipos de caracteres utilizar. Podrías hacerlo así:
function randomString(length, chars) {
var mask = '';
if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (chars.indexOf('#') > -1) mask += '0123456789';
if (chars.indexOf('!') > -1) mask += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\';
var result = '';
for (var i = length; i > 0; --i) result += mask[Math.floor(Math.random() * mask.length)];
return result;
}
console.log(randomString(16, 'aA'));
console.log(randomString(32, '#aA'));
console.log(randomString(64, '#A!'));
Violín: http://jsfiddle.net/wSQBx/2/
Alternativamente, para utilizar el método base36 como se describe a continuación, puede hacer algo como esto:
function randomString(length) {
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
}
ACTUALIZADO: Solución de una sola línea, para 20 caracteres aleatorios (minúsculas alfanuméricas):
Array.from(Array(20), () => Math.floor(Math.random() * 36).toString(36)).join('');
O más corto con lodash:
_.times(20, () => _.random(35).toString(36)).join('');
Otra variación de respuesta sugerida por JAR.JAR.beans
(Math.random()*1e32).toString(36)
Al cambiar el multiplicador 1e32
puedes cambiar la longitud de una cadena aleatoria.