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

Tom*_*man 1593 javascript random

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

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

csh*_*net 2189

我认为这对你有用:

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));
Run Code Online (Sandbox Code Playgroud)

  • 这对于短字符串很好,但要注意,在这样的字符串上使用`+ =`会导致它具有O(n ^ 2)行为.如果要创建更长的字符串,则应创建一个单独的字符数组,并在最后将它们连接在一起. (108认同)
  • @dan_waterworth在几乎*任何*案件中它可能无关紧要:http://www.codinghorror.com/blog/2009/01/the-sad-tragedy-of-micro-optimization-theater.html (90认同)
  • @JonathanPaulson*给我看数字*.使用jsperf链接或http://jsperf.com/sad-tragedy-of-microoptimization或http://www.sitepen.com/blog/2008/05/09/string-performance-an-analysis查看上一条评论/等等,此问题仅涉及5个连接. (16认同)
  • @dan_waterworth,实际上,`+ =`由于某种原因通常更快,甚至在循环中使用 - http://jsperf.com/join-vs-concatenation (7认同)
  • @codenamejames请*在密码腌制中使用*.它只是伪随机不安全.假设您正在使用Node(如果您在客户端进行腌制,我甚至不确定从哪里开始),请使用[`crypto`](http://nodejs.org/api/crypto.html). (7认同)
  • 它可能看起来不对,但是`floor`是不需要的:for(var text =''; text.length <5;)text + = possible.charAt(Math.random()*possible.length) (3认同)
  • @AlexReece那个链接没有说出你的想法.做一百万次"a"+"b"就可以了.做一次+ ="b"一百万次不是. (2认同)
  • @dan_waterworth - 你所说的在其他语言中是正确的,而不是在 javascript 中。 (2认同)
  • 所以我只是碾压了一些数字(关于```1000万```时间)和5个字符你得到一个```0.05%```复制相当一致,当你把字符提升到%%关于```0.0001%```.我计划在我的密码腌制中使用它,我将使用10个字符兰特字符串,我认为它将是完美的! (2认同)
  • @Hydro Thermal 密码上使用的盐通常可以被假定为公共信息,并且不需要加密安全。它的存在纯粹是为了降低预先计算的彩虹表存在的风险。 (2认同)
  • 这个关于性能的无关讨论是什么?谁想生成一百万个字符的随机字符串?如果在 2017 年我们仍然需要在编写字符串连接时窥探引擎盖,我们根本没有取得任何进展。 (2认同)

dou*_*tap 2186

let r = Math.random().toString(36).substring(7);
console.log("random", r);
Run Code Online (Sandbox Code Playgroud)

注意:上述算法有以下缺点:

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

  • `Math.random().toString(36).substr(2,5)`,因为`.substring(7)`导致它长于5个字符.满分,还在! (262认同)
  • 盖伊,这几乎没用.运行它只有1000000次,你通常会重复出现110000次:var values = {},i = 0,duplicateCount = 0,val; while(i <1000000){val = Math.random().toString(36).substring(7); if(values [val]){duplicateCount ++; } values [val] = 1; 我++; } console.log("TOTAL DUPLICATES",duplicateCount); (83认同)
  • @Scoop javascript中数字类型的`toString`方法采用可选参数将数字转换为给定的基数.例如,如果你传递两个,你会看到你的数字用二进制表示.类似于十六进制(基数16),基数36使用字母来表示超过9的数字.通过将随机数转换为基数36,您将得到一堆看似随机的字母和数字. (77认同)
  • 看起来很漂亮,但在少数情况下会产生空字符串!如果随机返回0,0.5,0.25,0.125 ......将导致空或短字符串. (72认同)
  • @gertas这可以通过`(Math.random()+ 1).toString(36).substring(7); (65认同)
  • @hacklikecrack,重复出现是因为`substring(7)`从base-36字符串的最不重要部分获取数字.`toString(36)`似乎将随机数转换为16位base-36字符串,但是这需要的精度为36 ^ 16 = 7.958e24个可能的数字,其中Math.random()的精度仅为[ 4.5e15](http://stackoverflow.com/questions/3344447/math-random-question).使用`.slice(2,5)`取最重要的数字来解决这个问题:[5位数示例](http://jsfiddle.net/dbbfmfdL/) (32认同)
  • 喜欢它,但他需要[a-zA-Z] (15认同)
  • `(+ new Date*Math.random()).toString(36).substring(0,5)` (9认同)
  • 好的解决方案 但是,我宁愿使用切片,因此字符数与给定参数匹配.`的Math.random().的toString(36).slice(-5)` (7认同)
  • 总而言之,使用@GeorgeReith和dragon技术的最终脚本是:(Math.random()+1).toString(36).substr(2,5).它会停止字符串为空并将其限制为5个字符. (5认同)
  • 我不知道它是否无用,但hacklikecrack完全是在说实话.csharptest.net的算法产生的重复数据少得多.如果你将数字位数增加到8,你会发现重复数字会降为零.谢谢你@hacklikecrack (4认同)
  • "0"修正:`('0000'+ Math.random().toString(36).replace('.','')).substr(-5);` (3认同)
  • 这会产生更长的随机数:(Math.PI*Math.max(0.01,Math.random())).toString(36).substr(2,5); (2认同)
  • @ william44isme:如果Math.random()返回0.25,那么上面将评估为`(1.25).toString(36).substr(2,5)`,它将等于`9` - 所以它仍然不起作用.我这样做:`函数randomString(){var i =''; while(i.length <5){i = Math.random().toString(36).slice(2);}; 回归我; }`,它给我一串至少5的字符串 (2认同)
  • 该解决方案仅部分回答了这个问题.它将生成一个随机的部分字符串`[a-z0-9]`.它不包括大写字母.尽管如此,仍然是一个非常好的技巧! (2认同)
  • 这可能无法在较新版本的Chrome中按预期工作(http://thenextweb.com/google/2015/12/17/google-chromes-javascript-engine-finally-returns-actual-random-numbers/#gref) (2认同)
  • 我在大约 9 年前写了这个答案,作为一种下意识的反应,没有显示出完全正确的答案(我的意图错误),而只是显示了一种可能不同的思考问题的方式。当时没有和我类似的答案。根据上面的评论,我想我实现了我的目标。 (2认同)

Tha*_*you 390

Math.random对这种事情不好

选项1

如果你能够在服务器端执行此操作,只需使用加密模块即可

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

// "bb5dc8842ca31d4603d6aa11448d1654"
Run Code Online (Sandbox Code Playgroud)

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


选项2

如果你必须做这个客户端,也许尝试uuid模块

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

// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"
Run Code Online (Sandbox Code Playgroud)

选项3

如果你必须在客户端做这个并且你不必支持旧的浏览器,你可以做到没有依赖

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

// 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"
Run Code Online (Sandbox Code Playgroud)

  • 你应该在答案中提到选项2也需要node.js才能工作,它不是纯粹的javascript. (4认同)
  • 究竟。尽管UUID可以为事物分配ID,但出于这个(可能还有其他)原因,将其用作一串随机字符并不是一个好主意。 (3认同)
  • 选项 3 中不需要 `.map()`。`Array.from(arr, dec2hex).join('')` === `Array.from(arr).map(dec2hex).join('') `. 感谢您向我介绍这些功能:-) (3认同)
  • 尽管在密码学上更安全,但这实际上不能满足问题的要求,因为它仅输出0-9和af(十六进制),而不输出0-9,az,AZ。 (3认同)

Sil*_*vee 162

简短,轻松,可靠

返回5个随机字符,而不是这里找到的一些最高评分的答案.

Math.random().toString(36).substr(2, 5);
Run Code Online (Sandbox Code Playgroud)

  • 如果`Math.random()。toString(36)`返回一个少于5个字符的数字怎么办? (5认同)
  • @rinogo Math.random()可以返回0而不是1 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random (5认同)
  • 我运行此代码1,000,000,000次仍然没有得到一个空字符串:jsfiddle.net/mtp5730r我会说你得到一个空字符串非常安全. (4认同)
  • 嗯,这是来自@Aperçu的一个有趣的起诉书,我并不是说我发明了解决方案,但我已经在我的项目中使用它多年了.它与你提到的评论无关.而且我很确定在最重要的地方,最重要的信息是在正确的地方,即使它已经存在于其他地方.幸运的是,似乎至少有51个人发现这个答案很有用,欢迎你! (3认同)
  • 为了避免在Math.random()返回0的情况下得到空字符串,你可以使用`function getRandomString(){var result =''; while(!result)result = Math.random().toString(36).substring(2); 返回结果; };` (3认同)
  • 从统计上讲不太可能发生的事件并不会使它安全。如果有人将其用于任何与安全相关的活动,他们正在赌博'Math.random'的可能性不返回0。希望您永远不必调试此事件 (3认同)
  • 这并不总是返回5个字符。例如,((0.5).toString(36).substr(2,5)`产生`“ i”`)。 (2认同)

ami*_*air 152

这是doubletap优秀答案的改进.原件有两个缺点,在这里解决:

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

(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
Run Code Online (Sandbox Code Playgroud)

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

Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
Run Code Online (Sandbox Code Playgroud)

说明:

  1. 选择范围[0,1)中的随机数,即0(包括)和1(不包括)之间的随机数.
  2. 将数字转换为base-36字符串,即使用字符0-9和az.
  3. 用零填充(解决第一个问题).
  4. 切掉领先的'0' 前缀和额外的填充零.
  5. 重复字符串足够多次以使其中至少包含N个字符(通过将空字符串与用作分隔符的较短随机字符串连接起来).
  6. 从字符串中精确切割N个字符.

进一步思考:

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

更新:

以下是我提出的其他几种功能风格的单线.它们与上述解决方案的不同之处在于:

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

所以,说你选择的字母表是

var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Run Code Online (Sandbox Code Playgroud)

那么这两个是相同的,所以你可以选择更直观的你:

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

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

编辑:

我好像是qubyte,Martijn de Milliano提出了类似于后者的解决方案(kudos!),我不知何故错过了.因为它们一目了然看起来不那么短,所以无论如何我都会把它留在这里以防有人真的想要一个单线:-)

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


Val*_*tin 101

最紧凑的解决方案,因为slice比较短substring.从字符串末尾减去允许避免random函数生成的浮点符号:

Math.random().toString(36).slice(-5);
Run Code Online (Sandbox Code Playgroud)

甚至

(+new Date).toString(36).slice(-5);
Run Code Online (Sandbox Code Playgroud)

btoa(Math.random()).slice(0, 5);
btoa(+new Date).slice(-7, -2);
btoa(+new Date).substr(-7, 5);
Run Code Online (Sandbox Code Playgroud)

  • 确切地。;) 如果 `Math.random()` 返回 `0.5`,则结果是 `"0.i"`。不确定是否还有其他边缘情况。只是想指出这不是问题的正确答案([a-zA-Z0-9] 中的 5 个字符)。 (2认同)
  • @x-ray,我不会说这是正确的答案,我只是说这是上面 @doubletap 答案的紧凑版本。我个人使用 `(+new Date + Math.random())` 来防止这种情况。不管怎样,谢谢你的留言。 (2认同)

Caf*_*eek 93

这样的事情应该有效

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;
}
Run Code Online (Sandbox Code Playgroud)

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

var randomValue = randomString(5);

var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
Run Code Online (Sandbox Code Playgroud)

  • 不妨直接在“while”循环中递减“len” (2认同)

ken*_*bec 71

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));
Run Code Online (Sandbox Code Playgroud)

  • +1不包括字符列表.:) (15认同)
  • 同时`while(L - )`会这样做 (3认同)
  • 最好使用更健壮的 `'A'.charCodeAt(0)` 而不是幻数 `55`(对于 `61` 也是如此)。特别是因为,无论如何,在我的平台上,返回的幻数是“65”。该代码也将更好地自我记录。 (3认同)

Rok*_*jan 48

随机字符串生成器(Alpha-Numeric | Alpha | Numeric)

/**
 * RANDOM STRING GENERATOR
 *
 * Info:      http://stackoverflow.com/a/27872144/383904
 * Use:       randomString(length [,"A"] [,"N"] );
 * Default:   return a random alpha-numeric string
 * Arguments: If you use the optional "A", "N" flags:
 *            "A" (Alpha flag)   return random a-Z string
 *            "N" (Numeric flag) return random 0-9 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;
}
Run Code Online (Sandbox Code Playgroud)
randomString(10);        // "4Z8iNQag9v"
randomString(10, "A");   // "aUkZuHNcWw"
randomString(10, "N");   // "9055739230"
Run Code Online (Sandbox Code Playgroud)

玩得开心.jsBin演示


虽然上面使用了对所需(A/N,A,N)输出的附加检查,但是为了更好地理解, 我们将其分解为基本要素(仅限字母数字):

  • 创建一个接受参数的函数(随机字符串结果的所需长度)
  • 创建一个空字符串,var str = "";以便连接随机字符
  • 在循环内创建一个rand0到61 索引号(0..9 + A..Z + a..z = 62)
  • 创建一个条件逻辑调整/修复rand(因为它是0..61)将它递增一些数字(参见下面的例子)以获得正确的CharCode数字和相关的字符.
  • 循环内部连接到str一个String.fromCharCode( incremented rand )

让我们看一下Character表及其范围:

_____0....9______A..........Z______a..........z___________  Character
     | 10 |      |    26    |      |    26    |             Tot = 62 characters
    48....57    65..........90    97..........122           CharCode ranges
Run Code Online (Sandbox Code Playgroud)

Math.floor( Math.random * 62 )给出了0..61(我们需要的)范围. 如何修复(递增)随机以获得正确的charCode范围

      |   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     |
Run Code Online (Sandbox Code Playgroud)

上表中的条件运算逻辑:

   rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand +=  true  ? (  true   ? 55 else 61 ) else 48 ;
Run Code Online (Sandbox Code Playgroud)

如果您按照上述说明操作,则应该能够创建此字母数字代码段:

jsBin演示

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) ); // "7GL9F0ne6t"
Run Code Online (Sandbox Code Playgroud)

或者如果你愿意:

function randomString( n ) {
  var r="";
  while(n--)r+=String.fromCharCode((r=Math.random()*62|0,r+=r>9?(r<36?55:61):48));
  return r;
}
Run Code Online (Sandbox Code Playgroud)


Or *_*uan 46

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

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

  • 30是任意数字,您可以选择任何您想要的令牌长度
  • 36是您可以传递给numeric.toString()的最大基数,这意味着所有数字和az小写字母
  • 2是用来接从它看起来像这样的随机字符串的第3号:"0.mfbiohx64i",我们可以采取任何索引后0.

  • 这是最好的解决方案 (2认同)
  • 我还要添加一个`|| '0'`,这样如果 `Math.random()` 返回 `0` (它永远不会返回 `1`),它就会回退到 `0` 而不是 `undefined`。 (2认同)

Mas*_*cus 31

最简单的方法是:

(new Date%9e6).toString(36)
Run Code Online (Sandbox Code Playgroud)

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

这个问题是如果你在同一秒钟上调用它两次,它将生成相同的字符串.

更安全的方式是:

(0|Math.random()*9e6).toString(36)
Run Code Online (Sandbox Code Playgroud)

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

在两种方式中,第一部分生成随机数.该.toString(36)部分将数字转换为它的base36(alphadecimal)表示.

  • 我想要一个较长的随机字符串和一个尽可能短的例程(用于代码演示),它不需要在密码学上令人惊叹,只需产生一些漂亮的随机视觉“绒毛”。我最喜欢这个答案(你的第二个答案),所以谢谢你。我的两分钱:我可以通过少一次击键来击败它,它通常会产生 13 个随机字符(没有句点):`(Math.random()*1e20).toString(36)`。 (2认同)

fro*_*rli 28

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

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

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

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

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

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

紧凑的单行

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

上述的一个变体:

"     ".replaceAll(" ",()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62))
Run Code Online (Sandbox Code Playgroud)

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

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

加密安全版本,为了紧凑性而浪费熵,而且无论如何都是浪费,因为生成的字符串太短了:

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

或者,如果没有长度参数,它会更短:

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

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

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

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

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

上述的一个更简单的变体:

const c=()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0);
c()+c()+c()+c()+c();
// 6Qadw
Run Code Online (Sandbox Code Playgroud)


ben*_*ree 20

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

包含 0-9a-z

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

包含 0-9a-zA-Z

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


小智 19

我知道每个人都已经把它弄好了,但我觉得可以用最轻量级的方式去做这个(代码轻,不是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));
Run Code Online (Sandbox Code Playgroud)

我们需要一些时间来解决这个问题,但我认为它确实展示了javascript的语法是多么棒.

  • 如果你试图保持代码简短,为什么写`current = current?current:'';`什么时候可以写`current = current || ""'; (20认同)
  • 因为我们在这里讨论微优化,所以我实际上建议完全跳过变量赋值,如果没有必要:`current || (current ='');` (8认同)

gog*_*ogo 18

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

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

console.log(generateUID(22)); // "yFg3Upv2cE9cKOXd7hHwWp"
console.log(generateUID(5)); // "YQGzP"
Run Code Online (Sandbox Code Playgroud)


vin*_*eet 16

如果你正在使用Lodash下划线,那么就这么简单:

var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
Run Code Online (Sandbox Code Playgroud)

  • Lodash使用`_.sampleSize('asdfgh',5).join('')` (6认同)
  • 这实际上不是一个好的解决方案,因为_per docs_每个字符都来自唯一索引。这意味着它不是真正随机的,因为没有字符可以/将不会重复。 (2认同)

Nah*_*eco 14

const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
Run Code Online (Sandbox Code Playgroud)


Zee*_*Zee 14

改进了上面@Andrew 的回答:

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

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


Ada*_*dam 13

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

工作示例:
http ://jsfiddle.net/greatbigmassive/vhsxs/ (仅限alpha)
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;
}
Run Code Online (Sandbox Code Playgroud)

升级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)));
}
Run Code Online (Sandbox Code Playgroud)


ark*_*dyt 13

一个班轮:

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


Mar*_*ano 12

如果有人对单线程感兴趣(虽然为了方便起见没有格式化),一次分配内存(但请注意,对于小字符串,它确实无关紧要)以下是如何做到这一点:

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

您可以用5所需字符串的长度替换.感谢@AriyaHidayat在这篇文章中解决了map函数不能处理由创建的稀疏数组Array(5).

  • 如果您将其格式化,则每个javascript程序都是"单行" (13认同)

tik*_*tak 12

假设您使用underscorejs,可以在两行中优雅地生成随机字符串:

var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
Run Code Online (Sandbox Code Playgroud)

  • 这将使返回的值具有所有唯一的字符.此外,字符串的长度限制为可能的长度. (6认同)

Ser*_*ral 12

满足要求[a-zA-Z0-9]和长度= 5使用

btoa(Math.random()).substr(5, 5);
Run Code Online (Sandbox Code Playgroud)

将出现小写字母,大写字母和数字.

  • 我想, Math.random() 可能会导致 base64 字符串的字符太少。 (3认同)

Ste*_*uan 11

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

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

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


qub*_*yte 9

这个小巧的小技巧怎么样?

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('');
Run Code Online (Sandbox Code Playgroud)

您需要在Array.apply那里将空数组欺骗为未定义数组。

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

var randomString = Array.from({ length: stringLength }, pickRandom).join('');
Run Code Online (Sandbox Code Playgroud)


Kam*_*ski 9

加密强

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

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``
Run Code Online (Sandbox Code Playgroud)

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``
Run Code Online (Sandbox Code Playgroud)

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


yar*_*lav 8

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

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

    const possible =
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    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);
        }
    }

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

    return result;
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但概率不均匀.有62个可能的字符,`crypto.getRandomValues`返回256个唯一值之一.因为256没有除以62,所以最终获得字符AH的概率略高.我认为最好的解决方案是做YouTube所做的事情,只需在字符集中添加2个附加字符(可能是`-`和`_`).无论如何,伟大的工作 - 这个答案需要更多的爱:) (2认同)

小智 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));
Run Code Online (Sandbox Code Playgroud)


Tha*_*you 7

这是一种函数式风格的方法。性能不是最优的,但写起来很有趣 -

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
Run Code Online (Sandbox Code Playgroud)

很难超越 的清晰度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')),
])
Run Code Online (Sandbox Code Playgroud)

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


Ali*_*Ali 7

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

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));
Run Code Online (Sandbox Code Playgroud)

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

区分大小写的所有字符:

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

// usage
console.log(randStr(50));
Run Code Online (Sandbox Code Playgroud)

自定义字符

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
Run Code Online (Sandbox Code Playgroud)


fra*_*cis 7

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

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

console.log(rnd(12))
Run Code Online (Sandbox Code Playgroud)


Fil*_*man 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)],
    "",
  );
Run Code Online (Sandbox Code Playgroud)


Gaj*_*jus 6

function randomString (strLength, charSet) {
    var result = [];

    strLength = strLength || 5;
    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    while (--strLength) {
        result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
    }

    return result.join('');
}
Run Code Online (Sandbox Code Playgroud)

这很干净.它也很快,http://jsperf.com/ay-random-string.

  • 从`--strLength`切换到`strLength - 为我修正它. (2认同)

din*_*sky 6

回答“我需要随机字符串”问题(无论使用哪种语言)的问题实际上是每个解决方案都使用有缺陷的字符串长度基本规范。问题本身很少揭示为什么需要随机字符串,但是我会挑战您,很少需要长度为8的随机字符串。您总是需要一定数量的唯一字符串,例如,出于某些目的用作标识符。

获得严格唯一的字符串有两种主要方法:确定性(不是随机的)和存储/比较(繁琐的)。我们做什么?我们放弃了幽灵。我们代之以概率唯一性。也就是说,我们接受我们的字符串存在唯一性的风险(但很小)。在这里,了解碰撞概率很有帮助。

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

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

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

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

const string = random.string(bits)
Run Code Online (Sandbox Code Playgroud)

“ 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)
Run Code Online (Sandbox Code Playgroud)

“ 27b33372ade513715481f”

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


rav*_*shi 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('');

更改5substr(2, 5)调整到你需要的长度.


The*_*oob 6

一个班轮 [az]:

String.fromCharCode(97 + Math.floor(Math.random() * 26))
Run Code Online (Sandbox Code Playgroud)


小智 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>
Run Code Online (Sandbox Code Playgroud)


rop*_*siU 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;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这样的事情怎么样:Date.now().toString(36) 不是很随机,但是每次调用时都很短而且很独特。


pie*_*e6k 5

这是我的方法(使用 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
Run Code Online (Sandbox Code Playgroud)