在JavaScript中生成随机字符串/字符。

2782
我希望得到一个由随机选取的字符组成的5个字符的字符串,可用字符集为[a-zA-Z0-9]
使用JavaScript,最佳方法是什么?

87
警告:所有答案都不具有“真正的随机”结果!它们只是“伪随机”。在使用随机字符串进行保护或安全时,不要使用它们中的任何一个!!!请尝试使用以下其中一种API:http://www.random.org/ - Ron van der Heijden
22
请注意:HTML5 webcrypto randomness API 提供真正的随机性。 - mikemaccana
6
如果有人在这里寻求生成一个ID或唯一标识符,让你的数据库来完成这项工作,或者使用UUID库。 - Dan
使用JavaScript、Java、Python、Rust和Bash生成随机字符串:https://fe-tool.com/zh-cn/random-password - cwtuan
试试npm库random-ext - undefined
94个回答

8

加密强度

如果你想获得符合你要求的加密强度字符串(我看到有些答案使用了它,但给出了不合法的答案),请使用以下方法:

let pass = n=> [...crypto.getRandomValues(new Uint8Array(n))]
   .map((x,i)=>(i=x/255*61|0,String.fromCharCode(i+(i>9?i>35?61:55:48)))).join``

let pass = n=> [...crypto.getRandomValues(new Uint8Array(n))]
   .map((x,i)=>(i=x/255*61|0,String.fromCharCode(i+(i>9?i>35?61:55:48)))).join``

console.log(pass(5));

更新:感谢Zibri的评论,我更新了代码以获取任意长度的密码。


7

仅需一个简单的mapreduce实现即可:

const charset: string =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

const random1: string = [...Array(5)]
  .map((_) => charset[Math.floor(Math.random() * charset.length)])
  .join("");

const random2: string = [...Array(5)]
  .reduce<string>(
    (acc) => acc += charset[Math.floor(Math.random() * charset.length)],
    "",
  );

7
使用map的一行代码,可以对长度和字符进行完全控制。
const rnd = (len, chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') => [...Array(len)].map(() => chars.charAt(Math.floor(Math.random() * chars.length))).join('')

console.log(rnd(12))

6
这是一种函数式的方法。性能不够优化,但编写起来很有趣。

const char = a =>
  String .fromCharCode (a)

const irand = x =>
  Math .floor (Math .random () * x)

const sample = xs =>
  xs .at (irand (xs.length))

const range = x => y =>
  x > y
    ? []
    : [ x, ...range (x + 1) (y) ]

const srand = rs => n =>
  n <= 0
    ? ""
    : char (sample (rs)) + srand (rs) (n - 1)

const identifier = srand ([
  ...range (48) (57),   // include 0-9
  ...range (65) (90),   // include A-Z
  ...range (97) (122),  // include a-z
])

console .log (identifier (6))  //=> xUCXPI
console .log (identifier (10)) //=> JQvct8XeGt
console .log (identifier (20)) //=> ZVDwQSdRQLJEF5Wqjs17

很难超越标识符的清晰度。也许可以稍微改进一下 -

const ord = x =>
  x .charCodeAt (0)

const idGenerator = srand ([
  ...range (ord('0')) (ord('9')),
  ...range (ord('A')) (ord('Z')),
  ...range (ord('a')) (ord('z')),
])

玩得开心。让我知道你喜欢/学到了什么 ^_^


1
很棒的解决方案,我喜欢你从foldk导出fold :D - user6445533
什么是 UYfoldk?我尝试理解这个问题,但我对函数式编程不是很熟悉,说实话,我不知道该查什么。另外,我使用 Deno 进行了基准测试,将这种方法与等效的命令式方法进行比较,结果正如我所预料的那样,速度慢了4倍。 - Teodor Maxim
1
@TeodorMaxim 要理解 UY,您需要了解组合逻辑foldkfold(或 reduce)的一种变体,它使用传递风格。我重新制作了答案,使其更加实用,不再关注函数原语。您会发现此版本的性能大大提高。如果您有任何其他问题,请告诉我。 - Mulan
我使用了const irand = x => { let value: number | undefined const arr = new Uint8Array(1) while (value === undefined || value >= x) { self.crypto.getRandomValues(arr) value = arr.at(0) } return value }来避免使用Math.random。但是代码块在评论中显示效果不好... - micce

6

我没有找到一个干净的解决方案来支持大小写字母。

仅支持小写字母:

Math.random().toString(36).substr(2, 5)

在此基础上支持大小写字母:

Math.random().toString(36).substr(2, 5).split('').map(c => Math.random() < 0.5 ? c.toUpperCase() : c).join('');

substr(2, 5)中的5更改为所需长度。


6

以下是我的做法(使用了TypeScript)。

我决定写另一个回答,因为我没有看到任何简单的、使用现代js和干净代码的解决方案。

const DEFAULT_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

function getRandomCharFromAlphabet(alphabet: string): string {
  return alphabet.charAt(Math.floor(Math.random() * alphabet.length));
}

function generateId(idDesiredLength: number, alphabet = DEFAULT_ALPHABET): string {
  /**
   * Create n-long array and map it to random chars from given alphabet.
   * Then join individual chars as string
   */
  return Array.from({length: idDesiredLength}).map(() => {
    return getRandomCharFromAlphabet(alphabet);
  }).join('');
}

generateId(5); // jNVv7

5

这肯定能够奏效

<script language="javascript" type="text/javascript">
function randomString() {
 var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
 var string_length = 8;
 var randomstring = '';
 for (var i=0; i<string_length; i++) {
  var rnum = Math.floor(Math.random() * chars.length);
  randomstring += chars.substring(rnum,rnum+1);
 }
 document.randform.randomfield.value = randomstring;
}
</script>

5

生成10个字符长的字符串。长度由参数设定(默认为10)。

function random_string_generator(len) {
var len = len || 10;
var str = '';
var i = 0;

for(i=0; i<len; i++) {
    switch(Math.floor(Math.random()*3+1)) {
        case 1: // digit
            str += (Math.floor(Math.random()*9)).toString();
        break;

        case 2: // small letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 97); //'a'.charCodeAt(0));
        break;

        case 3: // big letter
            str += String.fromCharCode(Math.floor(Math.random()*26) + 65); //'A'.charCodeAt(0));
        break;

        default:
        break;
    }
}
return str;
}

4
一句话简述[a-z]:
String.fromCharCode(97 + Math.floor(Math.random() * 26))

你仍然需要将字符串组合到被要求的长度。而且这只会生成[a-b]小写字母之间的随机字符。那么大写字母和数字呢?问题中也提到了它们。 - denik1981

4

如果您只想要大写字母(A-Z):

randomAZ(n: number): string {
      return Array(n)
        .fill(null)
        .map(() => Math.random()*100%25 + 'A'.charCodeAt(0))
        .map(a => String.fromCharCode(a))
        .join('')
 }

如果你只希望第一个字母大写(A-Z),而其余部分小写(a-z):

function RandomWord(n: number): string {
    return Array(n)
      .fill(null)
      .map(() => Math.random()*100%25 + 'A'.charCodeAt(0))
      .map((a, i) => i === 0? String.fromCharCode(a) : String.fromCharCode(a+32))
      .join('')
}

集合应该是 [a-zA-Z0-9] - Filip Seman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接