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

Generate random string/characters in JavaScript

提问人:Tom Lehman 提问时间:8/29/2009 最后编辑:Kamil KiełczewskiTom Lehman 更新时间:11/23/2023 访问量:2812366

问:

我想要一个由从集合中随机挑选的字符组成的 5 个字符的字符串。[a-zA-Z0-9]

使用 JavaScript 执行此操作的最佳方法是什么?

JavaScript 字符串

评论

87赞 Ron van der Heijden 5/29/2013
警告:没有一个答案有结果!他们只是.使用随机字符串进行保护或安全时,请勿使用其中任何一个!!尝试以下 api 之一: random.orgtrue-randompseudo-random
22赞 mikemaccana 1/10/2016
注意 HTML5 webcrypto randomness API 提供真正的随机性。
6赞 Dan 8/14/2019
如果有人在这里想要生成 id 或唯一标识符,请让您的数据库完成这项工作或使用 UUID 库。
0赞 cwtuan 12/21/2022
使用 javascript、Java、Python、Rust、bash 的随机字符串
0赞 Bipul 10/30/2023
尝试 npm 库 random-ext

答:

3668赞 csharptest.net 8/29/2009 #1

我认为这对你有用:

function makeid(length) {
    let result = '';
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    const charactersLength = characters.length;
    let counter = 0;
    while (counter < length) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
      counter += 1;
    }
    return result;
}

console.log(makeid(5));

评论

126赞 Alex Reece 1/11/2013
@dan_waterworth 几乎在任何情况下,这可能都无关紧要:codinghorror.com/blog/2009/01/......
5赞 Collin Anderson 2/28/2013
它可能看起来不对,但不是必需的: for(var text=''; text.length < 5;) text += possible.charAt(Math.random() * possible.length)floor
11赞 Kamila Borowska 5/1/2013
实际上,由于某种原因,@dan_waterworth通常更快,甚至在循环中使用 - jsperf.com/join-vs-concatenation+=
22赞 Alex Reece 5/8/2013
@JonathanPaulson 给我看数字。请参阅带有 jsperf 链接或 jsperf.com/sad-tragedy-of-microoptimizationsitepen.com/blog/2008/05/09/string-performance-an-analysis 等的上一条评论。此外,这个问题只涉及 5 个串联。
25赞 Hydrothermal 1/10/2015
@codenamejames请不要在密码加盐中使用它。它只是伪随机的,不安全的。假设您正在使用 Node(如果您在客户端加盐,我什至不确定从哪里开始),请改用 crypto
119赞 CaffGeek 8/29/2009 #2

像这样的东西应该可以工作

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;
}

使用默认字符集 [a-zA-Z0-9] 调用或发送您自己的字符集:

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');

评论

0赞 David 9/1/2012
此处的示例变体可以在此处找到:mediacollege.com/internet/javascript/number/random.html
2赞 drzaus 3/6/2013
还不如直接在循环中递减lenwhile
0赞 Dinis Cruz 11/1/2014
谢谢,我刚刚在下面发布了这个例子的 coffeescript 变体:stackoverflow.com/a/26682781/262379
0赞 Nate Bunney 4/19/2017
如果这些要公开使用,那么你可能应该去掉元音。熵少一点,但更安全,因为你不能产生任何可能冒犯人的词。这就是我喜欢这个的原因,因为我可以发送我自己的字符串。干得好。
0赞 Fattie 5/6/2022
请注意,在 Node 服务器上,它很简单:(例如,3 个字节提供 6 个字符)crypto.randomBytes(3).toString('hex')
78赞 kennebec 8/29/2009 #3

function randomstring(L) {
  var s = '';
  var randomchar = function() {
    var n = Math.floor(Math.random() * 62);
    if (n < 10) return n; //1-10
    if (n < 36) return String.fromCharCode(n + 55); //A-Z
    return String.fromCharCode(n + 61); //a-z
  }
  while (s.length < L) s += randomchar();
  return s;
}
console.log(randomstring(5));

评论

0赞 mastaBlasta 1/18/2014
我最喜欢这个。您可以轻松地进行修改以接受额外的参数并仅返回 nums、lowers 或 caps。我不认为超压缩风格是必要的while(s.length< L) s+= randomchar();
3赞 vsync 6/17/2014
也会这样做while(L--)
3赞 Grumdrig 7/10/2017
最好使用更健壮的数字而不是幻数(同样对于 )。特别是因为,无论如何,在我的平台上,返回的神奇数字是 .该代码也将更好地自我记录。'A'.charCodeAt(0)556165
0赞 Waruyama 9/20/2018
我在这里创建了一个缩小优化(小 46 字节)的实现变体:stackoverflow.com/a/52412162
5赞 Vignesh 12/3/2009 #4

这是肯定有效的

<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>
26赞 Roderick 5/4/2011 #5

我知道每个人都已经做对了,但我觉得以最轻量级的方式尝试一下(轻代码,而不是 CPU):

function rand(length, current) {
  current = current ? current : '';
  return length ? rand(--length, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random() * 60)) + current) : current;
}

console.log(rand(5));

这需要一些时间来理解,但我认为它确实显示了 javascript 的语法是多么棒。

评论

23赞 CaffGeek 8/8/2011
如果你想保持代码简短,为什么要在可以写的时候写current = current ? current : '';current = current || '';
10赞 Thomas Heymann 12/13/2013
由于我们在这里谈论的是微优化,我实际上建议在没有必要的情况下完全跳过变量赋值:current || (current = '');
0赞 Mörre 6/26/2019
在使用“不错”但浪费资源的递归算法时尝试微优化是没有意义的:-)for 循环在 Javascript 中仍然是最好的,并且大大超过了递归,直到运行时的优化代码取得了真正的重大进展。
3148赞 doubletap 11/11/2011 #6

//Can change 7 to 2 for longer results.
let r = (Math.random() + 1).toString(36).substring(7);
console.log("random", r);

注意:上述算法存在以下弱点:

  • 它将生成 0 到 6 个字符之间的任何字符,因为在字符串化浮点时会删除尾随零。
  • 它很大程度上取决于用于串化浮点数的算法,该算法非常复杂。(请参阅论文“如何准确打印浮点数”。
  • Math.random()可能会产生可预测的(“随机的”,但不是真正的随机)输出,具体取决于实现。当您需要保证唯一性或不可预测性时,生成的字符串不适用。
  • 即使它生成了 6 个统一随机的、不可预测的字符,由于生日悖论,在只生成大约 50,000 个字符串后,你也会看到一个重复的字符。(平方(36^6) = 46656)

评论

331赞 dragon 5/7/2012
Math.random().toString(36).substr(2, 5),因为会导致其长度超过 5 个字符。满分,还是!.substring(7)
86赞 Chris Baker 1/4/2013
@Scoop javascript 中数字类型的方法采用可选参数将数字转换为给定的基数。例如,如果你传递两个,你会看到你的数字以二进制表示。与十六进制(以 16 为基数)类似,以 36 为基数使用字母来表示 9 以上的数字。通过将一个随机数转换为以 36 为基数,你最终会得到一堆看似随机的字母和数字。toString
85赞 gertas 3/16/2013
看起来很漂亮,但在少数情况下,这会生成空字符串!如果 random 返回 0、0.5、0.25、0.125...将导致空字符串或短字符串。
81赞 George Reith 8/12/2013
@gertas 这可以通过以下方式避免(Math.random() + 1).toString(36).substring(7);
35赞 Luke 12/4/2014
@hacklikecrack,之所以会出现重复,是因为从 base-36 字符串的最低有效部分获取数字。 似乎将随机数转换为 16 位以 36 为基数的字符串,但所需的精度为 36^16 = 7.958e24 个可能的数字,其中 Math.random() 的精度仅为 4.5e15。从最高有效端取数字可以解决这个问题: 5 位示例substring(7)toString(36).slice(2,5)
10赞 Andy 1/2/2012 #7

您可以遍历项目数组并以递归方式将它们添加到字符串变量中,例如,如果您想要一个随机 DNA 序列:

function randomDNA(len) {
  len = len || 100
  var nuc = new Array("A", "T", "C", "G")
  var i = 0
  var n = 0
  s = ''
  while (i <= len - 1) {
    n = Math.floor(Math.random() * 4)
    s += nuc[n]
    i++
  }
  return s
}

console.log(randomDNA(5));

13赞 Gajus 1/10/2013 #8
function randomString (strLength, charSet) {
    var result = [];
    
    strLength = strLength || 5;
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    
    while (strLength--) { // (note, fixed typo)
        result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
    }
    
    return result.join('');
}

这是尽可能干净的。它也很快,http://jsperf.com/ay-random-string

评论

0赞 AlexGrafe 11/22/2013
对我来说,这总是生成带有 :-/ 的随机字符串strLength - 1
4赞 AlexGrafe 11/22/2013
从 切换到 为我修复了它。--strLengthstrLength--
0赞 Fattie 5/6/2022
@Gajus我冒昧地纠正了明显的错别字。它是后缀,而不是前缀。strLength--
0赞 Sagive 8/6/2022
谢谢你,先生。将其包装在 func 中使其易于复制/粘贴 ❤️
5赞 ropsiU 1/11/2013 #9

生成 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;
}
19赞 Martijn de Milliano 2/19/2013 #10

如果有人对一次分配内存的单行代码(尽管为了方便起见而没有格式化)感兴趣(但请注意,对于小字符串来说,这真的无关紧要),以下是如何做到的:

Array.apply(0, Array(5)).map(function() {
    return (function(charset){
        return charset.charAt(Math.floor(Math.random() * charset.length))
    }('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')

您可以替换为所需字符串的长度。感谢@AriyaHidayat这篇文章中对函数不起作用的解决方案。5mapArray(5)

评论

22赞 hacklikecrack 12/1/2013
每个 javascript 程序都是“单行”,如果你这样格式化它
3赞 Steven DAmico 3/17/2013 #11

通过回答 Gertas 和 Dragon 提出的问题来扩展 Doubletap 的优雅示例。只需添加一个 while 循环来测试那些罕见的 null 情况,并将字符限制为 5 个。

function rndStr() {
    x=Math.random().toString(36).substring(7).substr(0,5);
    while (x.length!=5){
        x=Math.random().toString(36).substring(7).substr(0,5);
    }
    return x;
}

下面是一个 jsfiddle 提醒你一个结果:http://jsfiddle.net/pLJJ7/

2赞 nclu 3/21/2013 #12

这将生成一个随机的字母数字字符串,其长度为第一个/调用字符串的长度:

"12345".split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');

//or

String.prototype.rand = function() {return this.split('').map(function(){return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(62*Math.random()));}).join('');};
2赞 qubyte 4/2/2013 #13

同样基于doubletap的答案,这个可以处理任意长度的随机必需字符(仅较低),并不断生成随机数,直到收集到足够的字符。

function randomChars(len) {
    var chars = '';

    while (chars.length < len) {
        chars += Math.random().toString(36).substring(2);
    }

    // Remove unnecessary additional characters.
    return chars.substring(0, len);
}
10赞 qubyte 8/8/2013 #14

这个紧凑的小把戏怎么样?

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var stringLength = 5;

function pickRandom() {
    return possible[Math.floor(Math.random() * possible.length)];
}

var randomString = Array.apply(null, Array(stringLength)).map(pickRandom).join('');

你需要 there 来欺骗空数组,使其成为一个未定义的数组。Array.apply

如果您正在为 ES2015 编写代码,那么构建数组会更简单一些:

var randomString = Array.from({ length: stringLength }, pickRandom).join('');
15赞 Adam 8/28/2013 #15

这是我创建的方法。
它将创建一个包含大写和小写字符的字符串。
此外,我还包含了将创建字母数字字符串的函数。

工作示例:
http://jsfiddle.net/greatbigmassive/vhsxs/(仅字母)
http://jsfiddle.net/greatbigmassive/PJwg8/(字母数字)

function randString(x){
    var s = "";
    while(s.length<x&&x>0){
        var r = Math.random();
        s+= String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65));
    }
    return s;
}

2015 年 7 月升级
这做同样的事情,但更有意义,并且包括所有字母。

var s = "";
while(s.length<x&&x>0){
    v = Math.random()<0.5?32:0;
    s += String.fromCharCode(Math.round(Math.random()*((122-v)-(97-v))+(97-v)));
}

评论

0赞 erkanyildiz 1/21/2015
使用此功能,您永远无法获得大于“M”的大写字母或小于“n”的小写字母。
0赞 Adam 7/27/2015
真?哦!到时候可能会对它进行更多测试。嗯,但是,鉴于它是一个随机字符串,并且我们并不真正关心其中的字母(只要它们是随机的),那么它仍然会做我们希望它做的事情,这才是最重要的,但是的,将提供升级,谢谢。
1赞 18 revsguest271314 #16
",,,,,".replace(/,/g,function (){return "AzByC0xDwEv9FuGt8HsIrJ7qKpLo6MnNmO5lPkQj4RiShT3gUfVe2WdXcY1bZa".charAt(Math.floor(Math.random()*62))});

评论

4赞 brunoais 9/3/2014
正则表达式过多。太慢了。
4赞 Andrew Plank 9/23/2013 #17

这就是我用的。这里是一对夫妇的组合。我在循环中使用它,它生成的每个 ID 都是唯一的。它可能不是 5 个字符,但保证是唯一的。

var newId =
    "randomid_" +
    (Math.random() / +new Date()).toString(36).replace(/[^a-z]+/g, '');

评论

1赞 Milosz 12/12/2013
就其价值而言,这并不能保证是独一无二的,它只是很可能是独一无二的。考虑到 Math.random() 可能会返回两次零。此外,如果将两个不同的以 36 为基数的数字输入到 .replace(/[^a-z]+/g, '');具有相同的非数字字符序列(例如 abc1 和 abc2),它们将返回相同的 ID。
0赞 Slavik Meltser 11/1/2013 #18

从字符中随机化字符串的另一种好方法:A-Za-z0-9

function randomString(length) {
    if ( length <= 0 ) return "";
    var getChunk = function(){
        var i, //index iterator
            rand = Math.random()*10e16, //execute random once
            bin = rand.toString(2).substr(2,10), //random binary sequence
            lcase = (rand.toString(36)+"0000000000").substr(0,10), //lower case random string
            ucase = lcase.toUpperCase(), //upper case random string
            a = [lcase,ucase], //position them in an array in index 0 and 1
            str = ""; //the chunk string
        b = rand.toString(2).substr(2,10);
        for ( i=0; i<10; i++ )
            str += a[bin[i]][i]; //gets the next character, depends on the bit in the same position as the character - that way it will decide what case to put next
        return str;
    },
    str = ""; //the result string
    while ( str.length < length  )
        str += getChunk();
    str = str.substr(0,length);
    return str;
}
190赞 amichair 11/14/2013 #19

这是对doubletap出色答案的改进。原版有两个缺点,此处将解决这些问题:

首先,正如其他人所提到的,它产生短字符串甚至空字符串(如果随机数为 0)的概率很小,这可能会破坏您的应用程序。这是一个解决方案:

(Math.random().toString(36)+'00000000000000000').slice(2, N+2)

其次,原始版本和上述解决方案都将字符串大小 N 限制为 16 个字符。对于任何 N,以下将返回一个大小为 N 的字符串(但请注意,使用 N > 16 不会增加随机性或降低冲突概率):

Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)

解释:

  1. 在 [0,1] 范围内选择一个随机数,即介于 0(含)和 1(不含)之间。
  2. 将数字转换为以 36 为基数的字符串,即使用字符 0-9 和 a-z。
  3. 用零填充(解决第一个问题)。
  4. 切掉前导的“0.”前缀和额外的填充零。
  5. 重复字符串足够多次,使其中至少有 N 个字符(通过将空字符串与用作分隔符的较短随机字符串连接起来)。
  6. 从字符串中精确切出 N 个字符。

进一步的想法:

  • 此解决方案不使用大写字母,但在几乎所有情况下(没有双关语)都无关紧要。
  • 原始答案中 N = 16 处的最大字符串长度以 Chrome 为单位。在Firefox中,它是N = 11。但如前所述,第二种解决方案是关于支持任何请求的字符串长度,而不是关于添加随机性,所以它没有太大区别。
  • 所有返回的字符串都有相等的返回概率,至少只要 Math.random() 返回的结果均匀分布(无论如何,这不是加密强度的随机性)。
  • 并非所有可能返回大小为 N 的字符串。在第二种解决方案中,这是显而易见的(因为较小的字符串只是被复制),但在原始答案中也是如此,因为在转换为 base-36 时,最后几位可能不是原始随机位的一部分。具体来说,如果你看一下 Math.random().toString(36) 的结果,你会发现最后一个字符分布不均匀。同样,在几乎所有情况下,这都无关紧要,但我们从随机字符串的开头而不是结尾切片最终字符串,这样短字符串(例如 N=1)就不会受到影响。

更新:

以下是我想出的其他几个功能式单行代码。它们与上述解决方案的不同之处在于:

  • 他们使用明确的任意字母表(更通用,适合要求大写和小写字母的原始问题)。
  • 所有长度为 N 的字符串具有相等的返回概率(即字符串不包含重复项)。
  • 它们基于 map 函数,而不是 toString(36) 技巧,这使得它们更加简单易懂。

所以,假设你选择的字母表是

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

那么这两者是相互等效的,所以你可以选择对你来说更直观的:

Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');

编辑:

我似乎 qubyteMartijn de Milliano 提出了类似于后者的解决方案(荣誉!),我不知何故错过了。由于它们乍一看并不短,所以我还是会把它留在这里,以防有人真的想要一个单行字:-)

此外,在所有解决方案中将“new Array”替换为“Array”,以减少更多字节。

评论

0赞 Mike Doe 1/8/2015
为什么不直接加 1?(Math.random()+1).toString(36).substring(7);
0赞 amichair 1/19/2015
因为添加 1 并不能解决此处讨论的两个问题中的任何一个。例如,(1).toString(36).substring(7) 生成一个空字符串。
0赞 Joseph Rex 11/13/2015
使用给出的预期结果更像是Math.random().toString(36).substring(2,7).substring(2, n+2)
0赞 Muhammad Umer 11/13/2015
Array.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
0赞 Edward Newell 6/11/2016
这很好,但是当在 Firefox 中以 N=16 执行时,最后 ~6 位数字最终为零......(但它确实满足了 OP 对 5 个随机字符的渴望。
2赞 mindrones 4/16/2014 #20

如果图书馆是可能的,Chance.js 可能会有所帮助:http://chancejs.com/#string

1赞 Collin Anderson 7/1/2014 #21

这会在变量 c 中存储 5 个字母数字字符。

for(var c = ''; c.length < 5;) c += Math.random().toString(36).substr(2, 1)
37赞 bendytree 7/18/2014 #22

这里有一些简单的衬里。更改以设置长度。new Array(5)

包括0-9a-z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);})

包括0-9a-zA-Z

new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});

Codegolfed for ES6 (0-9a-z)

Array(5).fill().map(n=>(Math.random()*36|0).toString(36)).join('')
4赞 James Harrington 8/7/2014 #23

这是 #1 答案的测试脚本(谢谢@csharptest.net)

脚本运行时间,正如你所看到的,5 并不是一个非常独特的。以 10 的字符长度运行它非常可靠。我已经运行了大约 50 次,但还没有看到重复的makeid()1 million:-)

注意:节点堆栈大小限制超过 400 万左右,因此您不能运行这 500 万次,它永远不会完成。

function makeid()
{
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for( var i=0; i < 5; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

ids ={}
count = 0
for (var i = 0; i < 1000000; i++) {
    tempId = makeid();
    if (typeof ids[tempId] !== 'undefined') {
        ids[tempId]++;
        if (ids[tempId] === 2) {
            count ++;
        }
        count++;
    }else{
        ids[tempId] = 1;
    }
}
console.log("there are "+count+ ' duplicate ids');
-2赞 Dinis Cruz 11/1/2014 #24

下面是 CoffeeScript 中的一个示例:

String::add_Random_Letters   = (size )->
                                         charSet = 'abcdefghijklmnopqrstuvwxyz'
                                         @ + (charSet[Math.floor(Math.random() * charSet.length)]  for i in [1..size]).join('')

可以使用的

value = "abc_"
value_with_exta_5_random_letters = value.add_Random_Letters(5)
1赞 EricP 11/6/2014 #25

我喜欢 doubletap 的 Math.random().toString(36).substring(7) 答案的简洁,但并不像 hacklikecrack 正确指出的那样有那么多的碰撞。它生成了 11 个 chacter 字符串,但在 100 万个样本量中具有 11% 的重复率。

这是一个更长(但仍然很短)且速度较慢的替代方案,在 100 万个样本空间中只有 133 个重复项。在极少数情况下,字符串仍将短于 11 个字符:

Math.abs(Math.random().toString().split('')
    .reduce(function(p,c){return (p<<5)-p+c})).toString(36).substr(0,11);
917赞 Mulan 1/3/2015 #26

Math.random 对这种事情很糟糕

服务器端

使用节点加密模块 -

var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');

// "bb5dc8842ca31d4603d6aa11448d1654"

生成的字符串长度将是生成的随机字节的两倍;编码为十六进制的每个字节为 2 个字符。20 个字节将是 40 个字符的十六进制。


客户端

使用浏览器的加密模块 crypto.getRandomValues -

该方法允许您获取加密性很强的随机值。作为参数给出的数组填充了随机数(其加密含义为随机数)。crypto.getRandomValues()

// dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
function dec2hex (dec) {
  return dec.toString(16).padStart(2, "0")
}

// 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"

分步控制台示例 -

> var arr = new Uint8Array(4) # make array of 4 bytes (values 0-255)
> 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 ]

对于 IE11 支持,您可以使用 -

(window.crypto || window.msCrypto).getRandomValues(arr)

有关浏览器覆盖范围,请参阅 https://caniuse.com/#feat=getrandomvalues


客户端(旧浏览器)

如果您必须支持旧浏览器,请考虑类似uuid -

const uuid = require("uuid");
const id = uuid.v4();

// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"

评论

7赞 wmassingham 8/5/2015
完全。虽然 UUID 可以用于为事物分配 ID,但由于这个(可能还有其他)原因,将其用作随机字符字符串并不是一个好主意。
3赞 Fred Gandt 5/12/2017
在选项 3 中不需要。 === .感谢您向我介绍这些功能:-).map()Array.from(arr, dec2hex).join('')Array.from(arr).map(dec2hex).join('')
7赞 Esko 8/21/2018
你应该在答案中提到,选项 2 也需要 node.js 才能工作,它不是纯粹的 javascript。
12赞 qJake 10/18/2018
虽然在加密上更安全,但这实际上并不能满足问题的要求,因为它只输出 0-9 和 a-f(十六进制),而不是 0-9、a-z、A-Z。
1赞 Mulan 12/2/2020
@AneesAhmed777提供了一个示例编码器。您可以按照自己的选择来表示字节。我用你的建议更新了帖子。dec2hex
1赞 user1115652 1/9/2015 #27

这是针对 firefox chrome 代码(插件等)的

function randomBytes( amount )
{
    let bytes = Cc[ '@mozilla.org/security/random-generator;1' ]

        .getService         ( Ci.nsIRandomGenerator )
        .generateRandomBytes( amount, ''            )

    return bytes.reduce( bytes2Number )


    function bytes2Number( previousValue, currentValue, index, array )
    {
      return Math.pow( 256, index ) * currentValue + previousValue
    }
}

将其用作:

let   strlen   = 5
    , radix    = 36
    , filename = randomBytes( strlen ).toString( radix ).splice( - strlen )
75赞 Roko C. Buljan 1/10/2015 #28

随机字符串生成器(字母数字 |阿尔法 |数字)

/**
 * Pseudo-random string generator
 * http://stackoverflow.com/a/27872144/383904
 * Default: return a random alpha-numeric string
 * 
 * @param {Integer} len Desired length
 * @param {String} an Optional (alphanumeric), "a" (alpha), "n" (numeric)
 * @return {String}
 */
function randomString(len, an) {
  an = an && an.toLowerCase();
  var str = "",
    i = 0,
    min = an == "a" ? 10 : 0,
    max = an == "n" ? 10 : 62;
  for (; i++ < len;) {
    var r = Math.random() * (max - min) + min << 0;
    str += String.fromCharCode(r += r > 9 ? r < 36 ? 55 : 61 : 48);
  }
  return str;
}

console.log(randomString(10));      // i.e: "4Z8iNQag9v"
console.log(randomString(10, "a")); // i.e: "aUkZuHNcWw"
console.log(randomString(10, "n")); // i.e: "9055739230"


虽然上述对所需的 A/N、A、N 输出使用额外的检查, 让我们将其分解为基本要素(仅限字母数字),以便更好地理解:

  • 创建一个接受参数的函数(随机 String 结果的所需长度)
  • 创建一个空字符串,就像连接随机字符一样var str = "";
  • 在循环中创建一个从 0 到 61 (0..9+A..Z+a..z = 62)
  • 创建一个条件逻辑调整/固定 rand(因为它是 0..61),将其递增一些数字(参见下面的示例)以获得正确的数字和相关的字符。CharCode
  • 在循环中连接到一个strString.fromCharCode( incremented rand )

让我们想象一下 ASCII 字符表范围:

_____0....9______A..........Z______a..........z___________  Character
     | 10 |      |    26    |      |    26    |             Tot = 62 characters
    48....57    65..........90    97..........122           CharCode ranges

Math.floor( Math.random * 62 )给出一个范围(我们需要什么)。
让我们修复随机数以获得正确的 charCode 范围
0..61

      |   rand   | charCode |  (0..61)rand += fix            = charCode ranges |
------+----------+----------+--------------------------------+-----------------+
0..9  |   0..9   |  48..57  |  rand += 48                    =     48..57      |
A..Z  |  10..35  |  65..90  |  rand += 55 /*  90-35 = 55 */  =     65..90      |
a..z  |  36..61  |  97..122 |  rand += 61 /* 122-61 = 61 */  =     97..122     |

上表中的条件操作逻辑

   rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand +=  true  ? (  true   ? 55 else 61 ) else 48 ;

从上面的解释中,下面是生成的字母数字片段

function randomString(len) {
  var str = "";                                // String result
  for (var i = 0; i < len; i++) {              // Loop `len` times
    var rand = Math.floor(Math.random() * 62); // random: 0..61
    var charCode = rand += rand > 9 ? (rand < 36 ? 55 : 61) : 48; // Get correct charCode
    str += String.fromCharCode(charCode);      // add Character to str
  }
  return str; // After all loops are done, return the concatenated string
}

console.log(randomString(10)); // i.e: "7GL9F0ne6t"

或者,如果您愿意:

const randomString = (n, r='') => {
  while (n--) r += String.fromCharCode((r=Math.random()*62|0, r+=r>9?(r<36?55:61):48));
  return r;
};

console.log(randomString(10))

评论

1赞 Harley Lang 2/5/2021
由于我无法识别的原因,---,正如我上面的答案中使用的---当我比较具有不同 ES 版本的两个应用程序的输出时,无法可靠地生成相同的字符,并且此功能为我修复了这个问题,因为它不使用 !x.toString(36).toString()
45赞 MasqueradeCircus 3/12/2015 #29

最简单的方法是:

(new Date%9e6).toString(36)

这将根据当前时间生成 5 个字符的随机字符串。示例输出为 or 或4mtxj4mv904mwp1

这样做的问题是,如果你在同一秒内调用它两次,它将生成相同的字符串。

更安全的方法是:

(0|Math.random()*9e6).toString(36)

这将生成一个 4 或 5 个字符的随机字符串,总是不同的。示例输出类似于 or 或30jzm1r5914su1a

在这两种方式中,第一部分都会生成一个随机数。该部件将数字转换为其 base36(字母十进制)表示形式。.toString(36)

评论

0赞 Claies 3/12/2015
我不太确定这如何回答这个问题;这是一个已有 7 年历史的问题,已经有许多有效的答案。如果您选择提供新的答案,您应该格外小心,以确保您的答案得到很好的解释和记录。
1赞 seniorpreacher 7/15/2015
如果你使用Date,为什么不直接使用它,比如:(+new Date).toString(36)
2赞 Andrew Willems 2/28/2016
我想要一个带有尽可能短的例程(用于代码演示)的长随机字符串,它不需要在加密上令人惊叹,只需产生一些漂亮的随机视觉“绒毛”。我最喜欢这个答案(你的第二个),所以谢谢。我的两美分:我可以用少一个击键来击败它,它通常会产生 13 个随机字符(没有句点):。(Math.random()*1e20).toString(36)
1赞 user.friendly 10/12/2017
我对这个答案的一个疑虑是它不会使用恰好在原始问题中的 [AZ]。
1赞 Lawrence Dol 8/27/2022
“最简单的方法”根本不会创建随机字符串;它创建高度可预测的字符串,表面上看起来是随机的。
14赞 tiktak 5/18/2015 #30

假设你使用 underscorejs,那么只需两行就可以优雅地生成随机字符串:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');

评论

6赞 Yefu 11/21/2016
这将使返回的值具有所有唯一的字符。此外,字符串的长度被限制在可能的 var 长度内。
159赞 Valentin Podkamennyi 10/15/2015 #31

最紧凑的解决方案,因为 slicesubstring 短。从字符串末尾减去可以避免随机函数生成的浮点符号:

Math.random().toString(36).slice(-5);

甚至

(+new Date).toString(36).slice(-5);

更新:添加了另一种使用 btoa 方法的方法:

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));

评论

0赞 x-ray 7/13/2019
Math.random().toString(36).slice(-5);- 如果退货怎么办?Math.random()0.0
0赞 Valentin Podkamennyi 7/13/2019
@x射线,你会得到"0" ;)
3赞 x-ray 7/13/2019
完全。;)如果返回,则结果为 。不确定是否有其他边缘情况。只是想指出这不是问题的正确答案([a-zA-Z0-5] 中的 0 个字符)。Math.random()0.5"0.i"
2赞 Valentin Podkamennyi 7/14/2019
@x射线,我不会说这是正确的答案,我只是说这是上面@doubletap答案的精简版本。我个人用来防止这种情况。无论如何,感谢您的笔记。(+new Date + Math.random())
1赞 Or Duan 11/14/2020
为什么不使用?我评论了其他答案,但使用此测试用例,您可以看到 base64 必须提供的 64 个字符中的 14 个字符:bota[...new Set([...Array(100000)].map(()=>btoa(Math.random()).substr(0, 5)).join(""))].sort()
1赞 user1506145 11/23/2015 #32

将字符放入 map 函数中将创建一个“单行”:thisArg

Array.apply(null, Array(5))
.map(function(){ 
    return this[Math.floor(Math.random()*this.length)];
}, "abcdefghijklmnopqrstuvwxyz")
.join('');
19赞 vineet 4/20/2016 #33

如果您使用的是 LodashUnderscore,那么它非常简单:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');

评论

9赞 marlo 8/24/2016
Lodash 使用_.sampleSize('asdfgh',5).join('')
5赞 random_user_name 11/5/2017
这实际上不是一个好的解决方案,因为每个文档每个字符都来自一个唯一的索引。这意味着它不是真正随机的,因为没有角色可以/永远不会重复。
-3赞 Alston 7/1/2016 #34

这是 Coffeescript 版本的一行代码

genRandomString = (length,set) -> [0...length].map( -> set.charAt Math.floor(Math.random() * set.length)).join('')

用法:

genRandomString 5, 'ABCDEFTGHIJKLMNOPQRSTUVWXYZ'

输出:

'FHOOV' # random string of length 5 in possible set A~Z
6赞 Mulan 7/2/2016 #35

下面是一种函数式方法。性能不理想,但写起来很有趣——

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

很难比 .也许稍微的改进可能是——identifier

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赞 7/23/2016
很棒的解决方案,我喜欢你从:Dfoldfoldk
0赞 Teodor Maxim 5/22/2023
什么是 和 ?我试图理解这一点,但我对函数式编程并不熟悉,老实说,我不知道该查找什么。此外,我使用 Deno 做了一个基准测试,将这种方法与等效的命令式方法进行比较,正如怀疑的那样,它慢😃了 4 倍UYfoldk
1赞 Mulan 5/23/2023
@TeodorMaxim理解,你将不得不研究组合逻辑。 是 (或 ) 的变体,它使用延续传递样式。我重新设计了答案,使其更实用,更少关注功能原语。您会发现此版本的性能得到了极大的提高。如果您有任何其他问题,请告诉我。UYfoldkfoldreduce
0赞 micce 7/31/2023
我曾经避免使用Math.random。但是代码块在注释中表现不佳......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 }
318赞 Silver Ringvee 7/28/2016 #36

短小精悍、简单可靠

返回 5 个随机字符,而不是此处找到的一些评分最高的答案。

Math.random().toString(36).slice(2, 7);

评论

25赞 Michael Litvin 1/17/2017
如果返回一个少于 5 个字符的数字怎么办?Math.random().toString(36)
8赞 Silver Ringvee 3/5/2017
嗯,这是@Aperçu的一个有趣的控诉,我并不是说我发明了解决方案,但我已经在我的项目中使用它多年了。这与你提到的评论无关。而且我很确定,在 SO 中,重要的是在正确的地方提供最有用的信息,即使它已经存在于其他地方。幸运的是,似乎至少有 51 个人发现这个答案很有用,不客气!
6赞 mikep 8/4/2017
@rinogo Math.random() 可以返回 0 但不能返回 1 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
10赞 MacroMan 7/19/2018
我运行了这段代码 1,000,000,000 次,但仍然没有得到一个空字符串:jsfiddle.net/mtp5730r 我会说你很安全,不会得到一个空字符串。
25赞 Purefan 3/15/2019
从统计学上讲不太可能发生的事件并不能使其安全。如果有人将其用于任何与安全相关的活动,他们就是在押注不返回 0 的不可能性。希望您永远不必调试此事件Math.random
0赞 aleung 8/5/2016 #37

npm 模块 anyid 提供了灵活的 API 来生成各种字符串 ID/代码。

const id = anyid().encode('Aa0').length(5).random().id();
11赞 yaroslav 9/17/2016 #38

快速和改进的算法。不保证统一(见评论)。

function getRandomId(length) {
    if (!length) {
        return '';
    }

    const possible =
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let array;

    if ('Uint8Array' in self && 'crypto' in self && length <= 65536) {
        array = new Uint8Array(length);
        self.crypto.getRandomValues(array);
    } else {
        array = new Array(length);

        for (let i = 0; i < length; i++) {
            array[i] = Math.floor(Math.random() * 62);
        }
    }

    let result = '';

    for (let i = 0; i < length; i++) {
        result += possible.charAt(array[i] % 62);
    }

    return result;
}

评论

4赞 TeWu 5/19/2017
很好的答案,但概率并不均匀。有 62 个可能的字符,并返回 256 个唯一值之一。因为 256 没有除以 62,所以你最终得到字符 A-H 的概率略高。我认为最好的解决方案是做 YouTube 所做的,只需在字符集中添加 2 个额外的字符(可能和)。无论如何,伟大的工作 - 这个答案需要更多的爱:)crypto.getRandomValues-_
0赞 cowbert 12/15/2017
添加 - 和 _ 是个好主意,因为它将为您提供完整的 URL 安全 base64 集
4赞 Lukasz Wiktor 1/9/2017 #39

您可以使用 coderain。它是一个根据给定模式生成随机代码的库。用作大写和小写字符以及数字的占位符:#

var cr = new CodeRain("#####");
console.log(cr.next());

还有其他占位符,例如大写字母或数字。A9

可能有用的是,调用将始终为您提供唯一的结果,因此您不必担心重复。.next()

下面是一个演示应用程序,它生成一个唯一的随机代码列表

完全披露:我是 coderain 的作者。

评论

0赞 1/17/2017
不不不 - 使用本机方法。
-1赞 CMS 3/30/2017 #40

我使用var randId = 'rand' + new Date().getTime();

评论

4赞 Jochem Kuijpers 7/20/2017
这与随机相反。如果你需要随机 ID 并生成多个 ID,例如,使用此方法在 for 循环中,你可能会得到一些相同的 ID。此外,用户可以通过设置计算机的日期/时间来影响您的 ID 选择。这不是您可能想做的事情。
0赞 CMS 7/21/2017
这真的取决于你需要什么,就我而言,当用户添加行时,我需要将 ID 添加到行中,而您不能在 1 毫秒内单击两次,
0赞 Jochem Kuijpers 7/31/2017
但是,当某些后台进程或其他 JavaScript 代码在浏览器上挂起几毫秒时,您可以双击,这会导致接下来的两个单击事件在“相同”毫秒内处理。当然,这不太可能发生,但这并非不可能。因此,代码是不可预测的。特别是如果您无法保证在您的网站/应用程序将运行的所有设备上运行时间等。
0赞 CMS 8/3/2017
我想看到一个演示,在我看来这是不可能的,除非你用机器人🤖点击
0赞 Jochem Kuijpers 8/11/2017
给你:gist.github.com/JochemKuijpers/86217cec7c860c0af0dfc06bbddacc42 我设法在 Chrome 上获得了一些相同的 ID(在我的第 6 代 i5 机器上很容易重现)。我可以想象,这在计时器不太准确的移动浏览器上更是一个问题。
0赞 Ratan Uday Kumar 6/21/2017 #41

在下面的代码中,我正在生成 8 个字符的随机代码

function RandomUnique(){
                    var charBank = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012346789";
                    var random= '';
                    var howmanycharacters = 8;
                    for (var i = 0; i < howmanycharacters ; i++) {
                        random+= charBank[parseInt(Math.random() * charBank.lenght)];
                    }
                    return random;
                }
        var random = RandomUnique();
        console.log(random);
0赞 anil kumar Dyavanapalli 6/24/2017 #42

试试这个,我每次都用到的:

function myFunction() {
        var hash = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012346789";
        var random8 = '';
        for(var i = 0; i < 5; i++){
            random8 += hash[parseInt(Math.random()*hash.length)];
        }
        console.log(random8);
    document.getElementById("demo").innerHTML = "Your 5 character string ===> "+random8;
}        
        
<!DOCTYPE html>
<html>
<body>

<p>Click the button to genarate 5 character random string .</p>

<button onclick="myFunction()">Click me</button>

<p id="demo"></p>



</body>
</html>

0赞 Behnam 7/3/2017 #43

很简单

function getRandomColor(){
  var color='';
  while(color.length<6){
    color=Math.floor(Math.random()*16777215).toString(16);
  }
  return '#'+color;
}
1赞 artnikpro 7/28/2017 #44

随机数值(最多 16 位)

/**
 * Random numeric value (up to 16 digits)
 * @returns {String}
 */
function randomUid () {
  return String(Math.floor(Math.random() * 9e15))
}

// randomUid() -> "3676724552601324"
9赞 dingo sky 9/3/2017 #45

回答“我需要随机字符串”问题(无论使用哪种语言)的问题在于,几乎每个解决方案都使用有缺陷的字符串长度的主要规范。这些问题本身很少能揭示为什么需要随机字符串,但我要挑战你很少需要长度的随机字符串,比如说 8。您总是需要一些唯一字符串,例如,用作某种目的的标识符。

有两种主要方法可以获取严格唯一的字符串:确定性(不是随机的)和存储/比较(繁重的)。我们该怎么办?我们放弃了幽灵。取而代之的是概率唯一性。也就是说,我们接受存在一些(无论多么小)的风险,即我们的字符串不是唯一的。这就是理解碰撞概率有帮助的地方。

因此,我将不变的需求重新表述为需要一定数量的字符串,重复的风险很小。举个具体的例子,假设你想生成 500 万个 ID 的潜力。您不希望存储和比较每个新字符串,并且希望它们是随机的,因此您接受一些重复的风险。例如,假设重复的风险小于万亿分之一。那么你需要多长的绳子呢?好吧,这个问题被低估了,因为它取决于所使用的字符。但更重要的是,它被误导了。你需要的是字符串熵的规范,而不是它们的长度。熵可以与某些字符串中重复的概率直接相关。字符串长度不能。

这就是像 EntropyString 这样的库可以提供帮助的地方。要生成在 500 万个字符串中重复的几率小于万亿分之一的随机 ID,请使用:entropy-string

import {Random, Entropy} from 'entropy-string'

const random = new Random()
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

“44hTNghjNHGGRHqH9”

entropy-string默认情况下,使用包含 32 个字符的字符集。还有其他预定义的字符集,您也可以指定自己的字符。例如,生成具有与上述相同熵但使用十六进制字符的 ID:

import {Random, Entropy, charSet16} from './entropy-string'

const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)

const string = random.string(bits)

“27b33372ade513715481f”

请注意,由于所用字符集中字符总数的差异,字符串长度存在差异。在指定数量的潜在字符串中重复的风险是相同的。字符串长度不是。最重要的是,重复的风险和潜在的字符串数量是明确的。无需再猜测字符串长度。

评论

0赞 Altay_H 12/5/2020
谢谢!您的评论让我意识到我不应该随机生成 ID。它看起来比我的目的更受欢迎,而且似乎也同样适合我的目的。nanoidentropy-string
1赞 Kerem 9/14/2017 #46

这是一种不同的方法,按基数固定长度,没有正则表达式替换缺失(基于 @bendytree 的回答);

function rand(base) {
    // default base 10
    base = (base >= 2 && base <= 36) ? base : 10;
    for (var i = 0, ret = []; i < base; i++) {
        ret[i] = ((Math.random() * base) | 0).toString(base)
            // include 0-9a-zA-Z?
            // [Math.random() < .5 ? 'toString' : 'toUpperCase']();
    }
    return ret.join('');
}
4赞 miodus 10/2/2017 #47

这个结合了给出的许多答案。

var randNo = Math.floor(Math.random() * 100) + 2 + "" + new Date().getTime() +  Math.floor(Math.random() * 100) + 2 + (Math.random().toString(36).replace(/[^a-zA-Z]+/g, '').substr(0, 5));

console.log(randNo);

我已经使用了 1 个月,效果很好。

0赞 Duco 10/3/2017 #48

教人钓鱼:

程序员用激光而不是电锯切纸。使用边缘的、特定于语言的方法来生成最小、最模糊的代码是可爱的,但永远不会提供完整的解决方案。您必须为工作使用正确的工具。

您需要的是字符串,字符由字节表示。而且,我们可以在 JavaScript 中使用数字表示一个字节。因此,我们应该生成这些数字的列表,并将它们转换为字符串。您不需要 Date 或 base64;Math.random() 会给你一个数字,而 String.fromCharCode() 会把它变成一个字符串。容易。

但是,哪个数字等于哪个字符?UTF-8 是 Web 上用于将字节解释为字符的主要标准(尽管 JavaScript 内部使用 UTF-16,但它们是重叠的)。程序员解决这个问题的方法是查看文档。

UTF-8 以 0 到 128 之间的数字列出键盘上的所有键。有些是非印刷的。只需在随机字符串中挑选出您想要的字符,然后使用随机生成的数字进行搜索。

波纹管是一个函数,它采用几乎无限的长度,在循环中生成一个随机数,并在较低的 128 个 UTF-8 代码中搜索所有打印字符。熵是固有的,因为并非所有随机数都会每次都命中(非打印字符、空白等)。当您添加更多字符时,它的性能也会更快。

我已经包含了线程中讨论的大多数优化:

  • 双波浪号比 Math.floor 快
  • “if”语句比正则表达式更快
  • 推送到数组比字符串连接更快

function randomID(len) {
  var char;
  var arr = [];
  var len = len || 5;

  do {
    char = ~~(Math.random() * 128);

    if ((
        (char > 47 && char < 58) || // 0-9
        (char > 64 && char < 91) || // A-Z
        (char > 96 && char < 123) // a-z

        // || (char > 32 && char < 48) // !"#$%&,()*+'-./
        // || (char > 59 && char < 65) // <=>?@
        // || (char > 90 && char < 97) // [\]^_`
        // || (char > 123 && char < 127) // {|}~
      )
      //security conscious removals: " ' \ ` 
      //&& (char != 34 && char != 39 && char != 92 && char != 96) 

    ) { arr.push(String.fromCharCode(char)) }

  } while (arr.length < len);

  return arr.join('')
}

var input = document.getElementById('length');

input.onfocus = function() { input.value = ''; }

document.getElementById('button').onclick = function() {
  var view = document.getElementById('string');
  var is_number = str => ! Number.isNaN( parseInt(str));
    
  if ( is_number(input.value))
    view.innerText = randomID(input.value);
  else
    view.innerText = 'Enter a number';
}
#length {
  width: 3em;
  color: #484848;
}

#string {
  color: #E83838;
  font-family: 'sans-serif';
  word-wrap: break-word;
}
<input id="length" type="text" value='#'/>
<input id="button" type="button" value="Generate" />
<p id="string"></p>

为什么要以这种乏味的方式进行?因为你可以。你是一名程序员。你可以让电脑做任何事情!此外,如果您想要一串希伯来语字符怎么办?这并不难。在 UTF-8 标准中找到这些字符并搜索它们。将自己从这些 McDonald 方法中解放出来,比如 toString(36)。

有时,创建真正的解决方案需要降低到较低的抽象级别。了解手头的基本原则可以让你按照自己的喜好自定义代码。也许你想要一个无限生成的字符串来填充一个循环缓冲区?也许您希望所有生成的字符串都是回文?为什么要让自己退缩?

评论

4赞 Victor Schröder 8/3/2018
天哪......维护此代码将很痛苦。太笨拙,不可读。总是为人类编写代码,这些代码最终可以由机器执行,而不是相反。而所有这些不必要的微优化都是纯粹的邪恶......CPU 周期很便宜。推送到数组是否比连接快,或者神秘的双波浪号是否比 快,这并不重要。Math.floor
0赞 Duco 8/21/2018
这都是基于意见的。自从我为这个答案编写代码以来,这段代码一直完美运行。我在分布式系统中使用它,该系统在高吞吐量期间每分钟广播更新并生成数千个唯一 ID。取消注释一行以添加字符的便利性非常简单。我看不出你的哲学“如果不需要就不要做”,程序员的空间不大。
0赞 redestructa 8/24/2018
我不知道。所有人都想编程,却忘记了他们面前有一台机器。在 80 年代,了解编程的数学是件好事。今天很高兴拥有?读取链式条件真的有什么大不了的吗?不!不适合我!嗯,语言很重要。但是说话的功能和符号对我来说是一个不错的选择。结合了两个世界,你就是一个熟练的程序员!我简直不敢相信投反对票。这不是堆栈溢出
2赞 Victor Schröder 9/11/2018
你@Duco误会我了。我不宣扬“如果不需要做,就不要做”。我不知道你从哪里得出这样的结论,我从来没有说过这样的话。实际上,我经常被批评重新发明轮子,我为此感到自豪!避免使用图书馆并自己做是件好事......有时!这是有限制的。 例如,是核心的一部分。我在这里的主要抱怨是代码很笨拙且难以阅读。顺便说一句,稍后使用的注释代码也是不好的做法。如果要控制函数的行为,请使函数采用另一个参数。Math.floor
4赞 Swergas 11/16/2017 #49

像这样的东西怎么样:不是很随机,但每次调用它时都很短且非常独特。Date.now().toString(36)

评论

1赞 Nate 1/29/2019
不幸的是,这并不是唯一的,因为只有毫秒级的分辨率。例如,当在一个简单的循环中运行时,你会得到很多重复项。.Date.now()for (let i = 0; i < 10; ++i) { console.log(Date.now().toString(36)); }
0赞 Sparw 11/21/2017 #50

我做了一个 String 原型,它可以生成一个给定长度的随机 String。

如果你想要特殊的字符,你也可以进行分类,你可以避免一些。

/**
 * STRING PROTOTYPE RANDOM GENERATOR
 * Used to generate a random string
 * @param {Boolean} specialChars
 * @param {Number} length
 * @param {String} avoidChars
 */
String.prototype.randomGenerator = function (specialChars = false, length = 1, avoidChars = '') {
    let _pattern = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    _pattern += specialChars === true ? '(){}[]+-*/=' : '';
    if (avoidChars && avoidChars.length) {
        for (let char of avoidChars) {
            _pattern = _pattern.replace(char, '');
        }
    }
    let _random = '';
    for (let element of new Array(parseInt(length))) {
        _random += _pattern.charAt(Math.floor(Math.random() * _pattern.length));
    }
    return _random;
};

你可以这样使用:

// Generate password with specialChars which contains 10 chars and avoid iIlL chars
var password = String().randomGenerator(true, 10, 'iIlL');

评论

1赞 Tyler Miller 3/16/2018
通常,扩展本机对象被认为是不好的做法(您可能会发布克苏鲁)。查看 - stackoverflow.com/questions/14034180/...
136赞 Or Duan 11/26/2017 #51

带有 es6 扩展运算符的较新版本:

[...Array(30)].map(() => Math.random().toString(36)[2]).join('')

  • 这是一个任意数字,你可以选择任何你想要的标记长度30
  • 这是您可以传递给 numeric.toString() 的最大基数,表示所有数字和 a-z 小写字母36
  • 用于从随机字符串中选择第 3 个索引,如下所示: ,我们可以在2"0.mfbiohx64i"0.

评论

0赞 vuza 12/5/2017
你能解释一下吗?特别是为什么将 36 传递给 toString() 以及为什么选择第 3 个元素?
0赞 Nahuel Greco 3/3/2020
很好,但此解决方案不包括问题要求的 [AZ] 字符,仅包含 [a-z0-9]
0赞 tam.teixeira 7/20/2020
@NahuelGreco你可以做[...数组(30)].map(() => Math.random().toString(36)[2]).join('').toUpperCase()
0赞 Nahuel Greco 7/20/2020
@tam.teixeira 我认为不,最初提出的问题是关于混合大写的,每个字符都必须从 [a-zA-Z0-9] 集合中随机选择。这个答案并不能满足这一点。
2赞 Juan Campa 8/8/2022
我还会添加一个,以便它回退到而不是 if returns(它永远不会返回|| '0'0undefinedMath.random()01)
6赞 ravishi 2/6/2018 #52

我没有找到支持小写和大写字符的干净解决方案。

仅支持小写字母:

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('');

更改 in 以调整到您需要的长度。5substr(2, 5)

0赞 user1300214 4/8/2018 #53

您可以使用 base64:

function randomString(length)
{
    var rtn = "";

    do {
        rtn += btoa("" + Math.floor(Math.random() * 100000)).substring(0, length);
    }
    while(rtn.length < length);

    return rtn;
}
2赞 Automatico 6/1/2018 #54

随机 unicode 字符串

此方法将返回一个包含任何支持的 unicode 字符的随机字符串,这不是 OP 要求的 100%,而是我一直在寻找的:

function randomUnicodeString(length){
    return Array.from({length: length}, ()=>{
        return String.fromCharCode(Math.floor(Math.random() * (65536)))
    }).join('')
}

理由

这是谷歌搜索“随机字符串javascript”时的顶级结果,但OP只要求a-zA-Z0-9。

73赞 Sergio Cabral 6/18/2018 #55

要满足要求 [a-zA-Z0-9] 和 5 个字符的长度,请使用

对于浏览器

btoa(Math.random().toString()).substring(10,15);

对于 NodeJS

Buffer.from(Math.random().toString()).toString("base64").substring(10,15);

将出现小写字母、大写字母和数字。

(它与打字稿兼容)

评论

6赞 Leif 6/25/2018
我想,Math.random() 可能会导致字符太少的 base64 字符串。
0赞 Or Duan 11/14/2020
加上@Leif评论,这只会生成 1-5 个字母中的 19-52 个数字,而只能生成 52 个字母中的 19 个!(大写和小写)要进行测试,只需多次运行它,它才能看到唯一的字符,然后进行排序。一个班轮:Set[...new Set([...Array(100000)].map(()=>btoa(Math.random()).substr(5, 5)).join(""))].sort()
0赞 Wojciech Bednarski 1/9/2022
为什么我们需要在浏览器示例中?toString
0赞 Sergio Cabral 1/12/2022
你是对的。不需要 .但是,当我想做一些事情时,“它与打字稿兼容”。所以我就这样离开了。toString()
1赞 nCoder 9/28/2022
我们可以改用 .substing(10,15) 吗?
0赞 Pascual Muñoz 8/17/2018 #56

递归解决方案:

function generateRamdomId (seedStr) {
const len = seedStr.length
console.log('possibleStr', seedStr , ' len ', len)
if(len <= 1){
    return seedStr
}
const randomValidIndex  = Math.floor(Math.random() * len)
const randomChar = seedStr[randomValidIndex]
const chunk1 = seedStr.slice(0, randomValidIndex)
const chunk2 = seedStr.slice(randomValidIndex +1)
const possibleStrWithoutRandomChar = chunk1.concat(chunk2)

return randomChar + generateRamdomId(possibleStrWithoutRandomChar)

}

你可以和你想要的种子一起使用,如果你不rea,就不要重复chars。例

generateRandomId("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") 
2赞 Waruyama 9/20/2018 #57

对于包含大写和小写字母和数字 (0-9a-zA-Z) 的字符串,这可能是最精简的版本:

function makeId(length) {
  var id = '';
  var rdm62;
  while (length--) {
   // Generate random integer between 0 and 61, 0|x works for Math.floor(x) in this case 
   rdm62 = 0 | Math.random() * 62; 
   // Map to ascii codes: 0-9 to 48-57 (0-9), 10-35 to 65-90 (A-Z), 36-61 to 97-122 (a-z)
   id += String.fromCharCode(rdm62 + (rdm62 < 10 ? 48 : rdm62 < 36 ? 55 : 61)) 
  }
  return id;
}

此函数的内容最小化为 97 个字节,而顶部答案需要 149 个字节(因为字符列表)。

10赞 Ali 9/23/2018 #58

不区分大小写的字母数字字符:

function randStr(len) {
  let s = '';
  while (s.length < len) s += Math.random().toString(36).substr(2, len - s.length);
  return s;
}

// usage
console.log(randStr(50));

这个函数的好处是你可以得到不同长度的随机字符串,它保证了字符串的长度。

所有字符均区分大小写:

function randStr(len) {
  let s = '';
  while (len--) s += String.fromCodePoint(Math.floor(Math.random() * (126 - 33) + 33));
  return s;
}

// usage
console.log(randStr(50));

自定义字符

function randStr(len, chars='abc123') {
  let s = '';
  while (len--) s += chars[Math.floor(Math.random() * chars.length)];
  return s;
}

// usage
console.log(randStr(50));
console.log(randStr(50, 'abc'));
console.log(randStr(50, 'aab')); // more a than b

评论

0赞 Denis.Sabolotni 10/11/2018
这个答案更适合我的用例。如果你能在可接受的答案中添加一个喜欢,那就太酷了,这样函数的结果就更可配置了。var possible
2赞 ceving 11/20/2018 #59

这是doubletap答案的略微改进版本。它考虑了 gertas 对案例的评论,当返回 0、0.5、0.25、0.125 等时。Math.random()

((Math.random()+3*Number.MIN_VALUE)/Math.PI).toString(36).slice(-5)
  1. 它可以防止将零传递给我将最小的浮点数添加到 。toStringMath.random()
  2. 它通过除以一个几乎无理数来确保传递给的数字有足够的数字。toString
1赞 Elias Zamaria 1/16/2019 #60

正如在座的几位人士所指出的,将结果直接传递给存在几个问题。Math.random().string(36)

它的随机性很差。生成的字符数各不相同,平均而言取决于浮点数在 Javascript 中如何工作的棘手细节。如果我尝试生成 11 个或更少的字符,但不能超过 11 个字符,它似乎有效。而且它不灵活。没有简单的方法可以允许或禁止某些字符。

我有一个紧凑的解决方案,对于使用 lodash 的任何人来说,它没有这些问题:

_.range(11).map(i => _.sample("abcdefghijklmnopqrstuvwxyz0123456789")).join('')

如果要允许某些字符(如大写字母)或禁止某些字符(如不明确的字符,如 和 ),请修改上面的字符串。l1

2赞 Alireza 1/29/2019 #61

下面这个怎么样......这将产生真正的随机值:

function getRandomStrings(length) {
  const value = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  const randoms = [];
  for(let i=0; i < length; i++) {
     randoms.push(value[Math.floor(Math.random()*value.length)]);
  }
  return randoms.join('');
}

但是,如果你在 ES6 中寻找一个更短的语法:

const getRandomStrings = length => Math.random().toString(36).substr(-length);
-1赞 Parth Raval 4/22/2019 #62

最重要的是,答案是完美的。但我正在添加非常好且快速生成任何随机字符串值

function randomStringGenerator(stringLength) {
  var randomString = ""; // Empty value of the selective variable
  const allCharacters = "'`~!@#$%^&*()_+-={}[]:;\'<>?,./|\\ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'"; // listing of all alpha-numeric letters
  while (stringLength--) {
    randomString += allCharacters.substr(Math.floor((Math.random() * allCharacters.length) + 1), 1); // selecting any value from allCharacters varible by using Math.random()
  }
  return randomString; // returns the generated alpha-numeric string
}

console.log(randomStringGenerator(10));//call function by entering the random string you want

console.log(Date.now())// it will produce random thirteen numeric character value every time.
console.log(Date.now().toString().length)// print length of the generated string

评论

0赞 Molomby 1/21/2020
Date.now()大多数肯定不会产生 13 个“随机”数字
0赞 Parth Raval 1/25/2020
@Molomby,兄弟,我很感激你的时间,但请写下逻辑,在这种情况下,它不会产生十三个“随机”数字。
1赞 Molomby 1/28/2020
随机性是缺乏可预测性。生成的数字表示调用函数的计算机的当前日期/时间。它们是高度可预测的,并且根本不是定义的任何“随机”。真正的随机性很难;甚至不是真正的随机,它是伪随机的。您将在此线程中看到其他答案,推荐更好的模块(但仍然不是真正随机的)。从这里开始了解更多信息: developer.mozilla.org/en-US/docs/Glossary/RNGDate.now()Math.random()crypto
6赞 Adam Pietrasiak 4/25/2019 #63

这是我的方法(使用 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
1赞 Sibevin Wang 5/17/2019 #64

我只是编写一个简单的包来生成一个具有给定大小、种子和掩码的随机令牌。仅供参考。

@sibevin/random-token - https://www.npmjs.com/package/@sibevin/random-token

import { RandomToken } from '@sibevin/random-token'

RandomToken.gen({ length: 32 })
// JxpwdIA37LlHan4otl55PZYyyZrEdsQT

RandomToken.gen({ length: 32, seed: 'alphabet' })
// NbbtqjmHWJGdibjoesgomGHulEJKnwcI

RandomToken.gen({ length: 32, seed: 'number' })
// 33541506785847193366752025692500

RandomToken.gen({ length: 32, seed: 'oct' })
// 76032641643460774414624667410327

RandomToken.gen({ length: 32, seed: 'hex' })
// 07dc6320bf1c03811df7339dbf2c82c3

RandomToken.gen({ length: 32, seed: 'abc' })
// bcabcbbcaaabcccabaabcacbcbbabbac

RandomToken.gen({ length: 32, mask: '123abcABC' })
// vhZp88dKzRZGxfQHqfx7DOL8jKTkWUuO
17赞 Nahuel Greco 6/1/2019 #65
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
0赞 Nixinova 2/1/2020 #66

简单方法:

function randomString(length) {
    let chars = [], output = '';
    for (let i = 32; i < 127; i ++) {
        chars.push(String.fromCharCode(i));
    }
    for (let i = 0; i < length; i ++) {
        output += chars[Math.floor(Math.random() * chars.length )];
    }
    return output;
}

如果您想要更多或更少的字符,请将“127”更改为其他内容。

15赞 iamarkadyt 3/21/2020 #67

一班:

Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil

评论

0赞 iamarkadyt 4/4/2020
为了缩短它,请将参数更改为较小的值。例如:.Array(15)Array(4)
0赞 Siscia 5/12/2020
我真的很喜欢这个解决方案,简单明了。它生成 0 到 1 之间的 15 个随机数,生成十六进制,然后删除前两个字符。最后,它将所有这些合并在一起。
0赞 Nahuel Greco 8/1/2021
错误的解决方案,不会生成大写字符。
-1赞 Abayomi Olowu 4/26/2020 #68

创建一个长度为 10 的随机代码,您可以随意将其更改为您的代码

function createRandomCode(length) {
    let randomCodes = '';
    let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let charactersLength = characters.length;
    for (let i = 0; i < length; i++ ) {
        randomCodes += characters.charAt(Math.floor(Math.random() * charactersLength))
    }
    console.log("your reference code is: ".toLocaleUpperCase() + randomCodes);
 };
 createRandomCode(10)

评论

2赞 RockyK 6/11/2020
这只是经过非常小修改的最佳答案之一。
0赞 Abayomi Olowu 3/12/2021
我只是试着让它更简单、更易读。
2赞 Marc 5/19/2020 #69

生成任意数量的十六进制字符(例如 32):

(function(max){let r='';for(let i=0;i<max/13;i++)r+=(Math.random()+1).toString(16).substring(2);return r.substring(0,max).toUpperCase()})(32);
8赞 Kamil Kiełczewski 6/22/2020 #70

加密强

如果您想获得符合您要求的加密强字符串(我看到答案使用它但给出无效的答案),请使用

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 评论,我更新代码以获取任意长的密码

0赞 Kamil Kiełczewski 6/22/2020 #71

回顾

许多答案都基于技巧,但这种方法的问题是 Math.random 并不总是产生以 5 为基数至少 36 个字符的数字,例如Math.random().toString(36)

let testRnd = n => console.log(`num dec: ${n}, num base36: ${n.toString(36)}, string: ${n.toString(36).substr(2, 5)}`);


[
  Math.random(),
  // and much more less than 0.5...
  0.5,
  0.50077160493827161,
  0.5015432098765432,
  0.5023148148148148,
  0.5030864197530864,
  // and much more....
  0.9799597050754459
].map(n=>testRnd(n));

console.log('... and so on');
Each of below example (except first) numbers result with less than 5 characters (which not meet OP question requirements)

这是允许手动查找此类数字的“生成器”

function base36Todec(hex) {
  hex = hex.split(/\./);
  return (parseInt(hex[1],36))*(36**-hex[1].length)+ +(parseInt(hex[0],36));
}

function calc(hex) {
  let dec = base36Todec(hex);
  msg.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${dec.toString(36)}</b>`
} 

function calc2(dec) {
  msg2.innerHTML = `dec: <b>${dec}</b><br>hex test: <b>${(+dec).toString(36)}</b>`
} 

let init="0.za1";
inp.value=init;
calc(init);
Type number in range 0-1 using base 36 (0-9,a-z) with less than 5 digits after dot<br>
<input oninput="calc(this.value)" id="inp" /><div id="msg"></div>
<br>
If above <i>hex test</i> give more digits than 5 after dot - then you can try to copy dec number to below field and join some digit to dec num right side and/or change last digit - it sometimes also produce hex with less digits<br>
<input oninput="calc2(this.value)" /><br><div id="msg2"></div>

我已经在这里给出了答案,所以我不会在这里提出另一个解决方案

0赞 jerrymouse 7/2/2020 #72

以下代码将使用 npm 包生成一个大小为 的加密保护随机字符串,其中包含 。使用以下方法安装它:[a-zA-Z0-9]crypto-random-string

npm install crypto-random-string

要获取集合 [a-zA-Z0-9] 中 30 个字符的随机字符串:

const cryptoRandomString = require('crypto-random-string');
cryptoRandomString({length: 100, type: 'base64'}).replace(/[/+=]/g,'').substr(-30);

摘要:我们将替换 /、+、= 替换为一个大的随机 base64 字符串,并获取最后 N 个字符。

附言:在 -N 中使用substr

0赞 Nirvana 7/4/2020 #73

如果无法键入字符集,则使用 和 ranged 允许您在任何 Unicode 代码点范围内创建随机字符串。例如,如果需要随机藏文字符,可以输入 ,其中对应于藏文 Unicode 块。在我的实现中,如果您不指定代码点范围,生成器将吐出文本。String.fromCharCodeMath.random17ranstr(17,0xf00,0xfff)(0xf00,0xfff)ASCII

    function ranchar(a,b) {
       a = (a === undefined ? 0 : a);
       b = (b === undefined ? 127 : b);
       return String.fromCharCode(Math.floor(Math.random() * (b - a) + a)); 
    }
    
    function ranstr(len,a,b) {
      a = a || 32;
      var result = '';
      for(var i = 0; i < len; i++) {
       result += ranchar(a,b)
      }
      return result;
    }


//Here are some examples from random Unicode blocks
console.log('In Latin Basic block: '+ ranstr(10,0x0000,0x007f))
console.log('In Latin-1 Supplement block: '+ ranstr(10,0x0080,0x0ff))
console.log('In Currency Symbols block: ' + ranstr(10,0x20a0,0x20cf))
console.log('In Letterlike Symbols block: ' + ranstr(10,0x2100,0x214f))
console.log('In Dingbats block:' + ranstr(10,0x2700,0x27bf))

1赞 user7793758 7/17/2020 #74

像这样扩展 String 对象怎么样。

String.prototype.random = function(length) {
   var result = '';
   for (var i = 0; i < length; i++) {
      result += this.charAt(Math.floor(Math.random() * this.length));
   }

   return result;
};

使用它:

console.log("ABCDEFG".random(5));
15赞 Zee 7/25/2020 #75

改进了上面@Andrew的答案:

Array.from({ length : 1 }, () => Math.random().toString(36)[2]).join('');

随机数的 Base 36 转换不一致,因此选择单个数字可以解决此问题。您可以使用所需的确切长度更改字符串的长度。

1赞 Dominicentek Gaming 8/9/2020 #76
function generate(length) {
  var letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9"];
  var IDtext = "";
  var i = 0;
  while (i < length) {
    var letterIndex = Math.floor(Math.random() * letters.length);
    var letter = letters[letterIndex];
    IDtext = IDtext + letter;
    i++;
  }
  console.log(IDtext)
}
25赞 gogo 8/12/2020 #77

生成一个安全的随机字母数字字符串:Base-62

function generateUID(length)
{
    return window.btoa(String.fromCharCode(...window.crypto.getRandomValues(new Uint8Array(length * 2)))).replace(/[+/]/g, "").substring(0, length);
}

console.log(generateUID(22)); // "yFg3Upv2cE9cKOXd7hHwWp"
console.log(generateUID(5)); // "YQGzP"

-1赞 Don Dilanga 12/31/2020 #78

这不是一个完美的解决方案,但它应该有效。如果出现任何错误,请增加 Uint8Array() 构造函数中给出的值。这种方法的优点是它使用 getRandomValues() 方法来生成加密强随机值。

var array = new Uint8Array(20);
crypto.getRandomValues(array);
var arrayEncoded =  btoa(String.fromCharCode(...array)).split('');
var arrayFiltered = arrayEncoded.filter(value => {
    switch (value){
    case "+" :
        return false;
    case "/" :
        return false;
    case "=" :
        return false;
    default :
      return true;
   }
});
var password = arrayFiltered.slice(0,5).join('');
console.log(password);

紧凑型版本

var array = new Uint8Array(20);
crypto.getRandomValues(array);
var password = btoa(String.fromCharCode(...array)).split('').filter(value => {
        return !['+', '/' ,'='].includes(value);
}).slice(0,5).join('');
console.log(password);

4赞 Denys Vitali 2/28/2021 #79

如果您只想要大写字母 (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('')
}

评论

0赞 Filip Seman 10/14/2021
该集应为[a-zA-Z0-9]
4赞 TheBotlyNoob 5/22/2021 #80

一个衬垫 [a-z]:

String.fromCharCode(97 + Math.floor(Math.random() * 26))

评论

0赞 denik1981 6/2/2021
您仍然需要将字符串组合到要求的长度。这只会生成 [a-b] 小写的随机字符。大写字母和数字呢,因为它也被问到了这个问题?
0赞 denik1981 6/2/2021 #81

喜欢这个 SO 问题和他们的答案。因此,提出了切肉刀和创造性的解决方案。我想出了我的,它被包装在一个函数中,该函数接收您想要获取的字符串的长度以及一个模式参数来决定您希望如何组成它。

Mode 是一个长度为 3 的字符串,仅接受“1s”和“0s”,用于定义要包含在最终字符串中的字符子集。它按 3 个不同的子集([0-9]、[AB]、[a-b]) 分组

'100': [0-9]
'010': [A-B]
'101': [0-9] + [a-b]
'111': [0-9] + [A-B] + [a-b]

有 8 种可能的组合(2^N,witn N:#subsets)。 '000' 模式返回一个空字符串。

function randomStr(l = 1, mode = '111') {
    if (mode === '000') return '';
    const r = (n) => Math.floor(Math.random() * n);
    const m = [...mode].map((v, i) => parseInt(v, 10) * (i + 1)).filter(Boolean).map((v) => v - 1);
    return [...new Array(l)].reduce((a) => a + String.fromCharCode([(48 + r(10)), (65 + r(26)), (97 + r(26))][m[r(m.length)]]), '')
}

一个简单的用例是:

random = randomStr(50, '101')
// ii3deu9i4jk6dp4gx43g3059vss9uf7w239jl4itv0cth5tj3e
// Will give you a String[50] composed of [0-9] && [a-b] chars only.

这里的主要思想是使用 UNICODE 表,而不是像我在许多答案中看到的那样随机化十六进制。这种方法的优点在于,您可以非常容易地扩展它,以包含UNICODE表的其他子集,其中包含随机int(16)无法做到的额外代码。

4赞 Siarhei Dudko 6/9/2021 #82

如果你在 node js 上开发,最好使用 crypto。下面是实现该函数的示例randomStr()

const crypto = require('crypto');
const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz';
const randomStr = (length = 5) => new Array(length)
    .fill(null)
    .map(() => charset.charAt(crypto.randomInt(charset.length)))
    .join('');

如果您不在服务器环境中工作,只需替换随机数生成器:

const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz';
const randomStr = (length = 5) => new Array(length)
    .fill(null)
    .map(() => charset.charAt(Math.floor(Math.random() * charset.length)))
    .join('');
1赞 dud3 7/14/2021 #83
[..."abcdefghijklmnopqrsuvwxyz0123456789"].map((e, i, a) => a[Math.floor(Math.random() * a.length)]).join('')
7赞 francis 7/21/2021 #84

使用地图的单行代码,可让您完全控制长度和字符。

const rnd = (len, chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') => [...Array(len)].map(() => chars.charAt(Math.floor(Math.random() * chars.length))).join('')

console.log(rnd(12))
27赞 frodeborli 9/28/2021 #85

没有最好的方法可以做到这一点。您可以按照自己喜欢的任何方式进行操作,只要结果符合您的要求即可。为了说明这一点,我创建了许多不同的示例,所有这些示例都应该提供相同的最终结果

此页面上的大多数其他答案都忽略了大写字符要求。

这是我最快的解决方案也是最具可读性的。它基本上与公认的解决方案相同,只是速度更快一些。

function readableRandomStringMaker(length) {
  for (var s=''; s.length < length; s += 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.charAt(Math.random()*62|0));
  return s;
}
console.log(readableRandomStringMaker(length));
// e3cbN

这是一个紧凑的递归版本,可读性要低得多:

const compactRandomStringMaker = (length) => length-- && "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0) + (compactRandomStringMaker(length)||"");
console.log(compactRandomStringMaker(5));
// DVudj

更紧凑的单行代码

Array(5).fill().map(()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62)).join("")
// 12oEZ

上述的变体:

"     ".replaceAll(" ",()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62))

最紧凑的单行代码,但效率低下且不可读 - 它添加随机字符并删除非法字符,直到长度为 l

((l,f=(p='')=>p.length<l?f(p+String.fromCharCode(Math.random()*123).replace(/[^a-z0-9]/i,'')):p)=>f())(5)

一个加密安全的版本,它浪费了熵来换取紧凑性,并且无论如何都是一种浪费,因为生成的字符串太短了:

[...crypto.getRandomValues(new Uint8Array(999))].map((c)=>String.fromCharCode(c).replace(/[^a-z0-9]/i,'')).join("").substr(0,5)
// 8fzPq

或者,如果没有 length-argument 它甚至更短:

((f=(p='')=>p.length<5?f(p+String.fromCharCode(Math.random()*123).replace(/[^a-z0-9]/i,'')):p)=>f())()
// EV6c9

然后更具挑战性 - 使用无名递归箭头函数

((l,s=((l)=>l--&&"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0)+(s(l)||""))) => s(l))(5);
// qzal4

这是一个“魔术”变量,每次访问它时都会提供一个随机字符:

const c = new class { [Symbol.toPrimitive]() { return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0) } };
console.log(c+c+c+c+c);
// AgMnz

上述的更简单变体:

const c=()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0);
c()+c()+c()+c()+c();
// 6Qadw
7赞 Filip Seman 10/12/2021 #86

只需一个简单的 or 实现就足够了: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)],
    "",
  );
2赞 Rick 10/21/2021 #87

发布一个 ES6 兼容版本供后代使用。如果调用次数很多,请确保将 .length 值存储到常量变量中。

// USAGE:
//      RandomString(5);
//      RandomString(5, 'all');
//      RandomString(5, 'characters', '0123456789');
const RandomString = (length, style = 'frictionless', characters = '') => {
    const Styles = {
        'all':          allCharacters,
        'frictionless': frictionless,
        'characters':   provided
    }

    let result              = '';
    const allCharacters     = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    const frictionless      = 'ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
    const provided          = characters;

    const generate = (set) => {
        return set.charAt(Math.floor(Math.random() * set.length));
    };

    for ( let i = 0; i < length; i++ ) {
        switch(Styles[style]) {
            case Styles.all:
                result += generate(allCharacters);
                break;
            case Styles.frictionless:
                result += generate(frictionless);
                break;
            case Styles.characters:
                result += generate(provided);
                break;
        }
    }
    return result;
}

export default RandomString;
1赞 Victor 11/12/2021 #88

使用 aA-zZ 和 0-9 个字符集合生成随机字符串。 只需使用长度参数调用此函数即可。

所以要回答这个问题:generateRandomString(5)

generateRandomString(length){
    let result = "", seeds

    for(let i = 0; i < length - 1; i++){
        //Generate seeds array, that will be the bag from where randomly select generated char
        seeds = [
            Math.floor(Math.random() * 10) + 48,
            Math.floor(Math.random() * 25) + 65,
            Math.floor(Math.random() * 25) + 97
        ]
        
        //Choise randomly from seeds, convert to char and append to result
        result += String.fromCharCode(seeds[Math.floor(Math.random() * 3)])
    }

    return result
}

生成不带数字的字符串的版本:

generateRandomString(length){
    let result = "", seeds

    for(let i = 0; i < length - 1; i++){
        seeds = [
            Math.floor(Math.random() * 25) + 65,
            Math.floor(Math.random() * 25) + 97
        ]
        result += String.fromCharCode(seeds[Math.floor(Math.random() * 2)])
    }

    return result
}
-1赞 NVRM 3/27/2022 #89

在此示例中,要从数组生成哈希值作为盐,通过这种方式,我们可以稍后检索哈希值以填充条件。[0,1,2,3]

只需输入随机数组,或用作额外安全和快速的阵列指纹。

/* This method is very fast and is suitable into intensive loops */
/* Return a mix of uppercase and lowercase chars */

/* This will always output the same hash, since the salt array is the same */
console.log(
  btoa(String.fromCharCode(...new Uint8Array( [0,1,2,3] )))
)

/* Always output a random hex hash of here: 30 chars  */
console.log(
  btoa(String.fromCharCode(...new Uint8Array( Array(30).fill().map(() => Math.round(Math.random() * 30)) )))
)

使用加密 API 中的 HMAC,了解更多信息:https://stackoverflow.com/a/56416039/2494754

-3赞 Arunprasanth M 5/11/2022 #90

返回随机字母

let alpha = "ABCDEFGHIGKLMNOPQRSTUVWXYZ";
console.log(alpha.charAt(Math.floor(Math.random() * alpha.length)));

评论

2赞 Asons 5/13/2022
请避免发布已经存在的解决方案。
0赞 Tiago Rangel 7/30/2022 #91

您可以使用 Web Crypto 的 API

console.log(self.crypto.getRandomValues(new Uint32Array(1))[0])

(原答案在这里)

评论

0赞 David Wheatley 2/24/2023
这只会生成随机数字字符串。
0赞 Tiago Bértolo 1/17/2023 #92
function generateRandomStringLettersAndNumbers(maxLength): string {
  return crypto.randomBytes(maxLength).toString('hex').substring(0, maxLength);
}
11赞 Stephen Quan 2/13/2023 #93

虽然这个答案与其他答案几乎相似,但它的不同之处在于它使用:

  • repeat创建 5 个字符(可以泛化为n)
  • repeat用正则表达式替换这 5 个字符/./g
  • 公式是从 62 个字符的 A-Za-z0-9 字符串中随机选择一个字符

let ans = "x".repeat(5)
             .replace(/./g, c => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[Math.floor(Math.random() * 62) ] );
console.log(ans);

1赞 Dr.Sai 11/15/2023 #94

在一行中

Array.from({ length: 5 }, i => String.fromCharCode(Math.round(Math.ceil(Math.random() * 25) + 65))).join('');
0赞 Felipe Buccioni 12/15/2023 #95

带有大写和小写的简化随机字母数字:

const l = 98 // length
Array.from(crypto.randomBytes(l)).reduce((s, b) => s + (b % 35).toString(36)[(b % 2) - 1 ? 'toLowerCase' : 'toUpperCase'](), '')