[a-zA-Z0-9]
。使用JavaScript,最佳方法是什么?
[a-zA-Z0-9]
。我认为这个方法适合你:
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));
floor
是不必要的:for(var text=''; text.length < 5;) text += possible.charAt(Math.random() * possible.length)(说明:这段代码是JavaScript中生成一个随机5位字符串的代码。原文想表达的是使用Math.random()
函数生成随机数时,向下取整操作floor
是可选的,因为该操作不影响最终结果。) - Collin Anderson+=
经常更快 - http://jsperf.com/join-vs-concatenation - Konrad Borowski//Can change 7 to 2 for longer results.
let r = (Math.random() + 1).toString(36).substring(7);
console.log("random", r);
Math.random()
可能会根据实现产生可预测(看起来像随机但实际上不是随机的)输出。当你需要保证唯一性或不可预测性时,生成的字符串不适合使用。Math.random().toString(36).substr(2, 5)
的意思是生成一个长度为5的随机字符串,其中包含字母和数字。使用 .substring(7)
会使字符串长度超过5个字符。无论如何,此代码仍然可以得到全部分数! - dragontoString
方法可以接受一个可选参数,将该数值转换为指定进制。例如,如果你传入 2,则会将数值转换为二进制表示。和十六进制(基数为 16)类似,三十六进制使用字母来表示大于 9 的数字。通过将随机数转换为三十六进制,你将得到一系列看起来毫无规律的字母和数字。 - Chris Baker(Math.random() + 1).toString(36).substring(7);
来避免。 - George Reithsubstring(7)
从base-36字符串的最低有效部分获取数字。toString(36)
似乎将随机数转换为16位base-36字符串,但需要的精度是36^16=7.958e24个可能的数字,而Math.random()的精度仅为4.5e15。通过使用.slice(2,5)
从最高有效端获取数字可以解决这个问题:5位数字示例。 - Luke服务器端
使用nodecrypto模块 -
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"
.map()
。Array.from(arr, dec2hex).join('')
与Array.from(arr).map(dec2hex).join('')
相同。感谢介绍这些功能 :-) - Fred Gandtdec2hex
提供了一个示例编码器。你可以自行选择如何表示字节。我已经根据你的建议更新了帖子。 - Mulan返回正好5个随机字符,与在此处找到的一些最受欢迎的答案相反。
Math.random().toString(36).slice(2, 7);
Math.random().toString(36)
返回的数字少于 5 个字符,那该怎么办? - Michael LitvinMath.random
不返回 0 的概率很小这个不确定性上。希望你永远不必调试这个事件。 - Purefan(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
其次,原始代码和上面的解决方案都将字符串大小N限制为16个字符。以下代码将返回任何大小为N的字符串(但请注意,使用N>16不会增加随机性或减少碰撞概率):
Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
解释:
进一步思考:
更新:
以下是我想到的几个函数式一行代码。它们与上面的解决方案不同之处在于: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('');
编辑:
看起来 qubyte 和 Martijn de Milliano 想到了类似后者的解决方案(赞!),但我不知道。由于它们一眼看上去不够简短,因此无论如何我都会在这里留下它,以防有人真的想要一个单行语句 :-)
此外,在所有解决方案中将 'new Array' 替换为 'Array' 以减少几个字节。
(Math.random()+1).toString(36).substring(7);
- Mike DoeMath.random().toString(36).substring(2,7)
可以得到一个预期的结果,这个结果更像是 .substring(2, n+2)
。 - Joseph RexArray.apply(null, {length: 5}).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('')
- Muhammad Umer最简洁的解决方案,因为slice
比substring
更短。从字符串末尾减去可以避免random
函数生成的浮点符号:
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));
Math.random().toString(36).slice(-5);
- 如果 Math.random()
返回 0.0
会怎样? - x-rayMath.random()
返回 0.5
,结果就是 "0.i"
。不确定是否还有其他边缘情况。只是想指出这不是问题(从 [a-zA-Z0-9] 中选取 5 个字符)的正确答案。 - x-ray(+new Date + Math.random())
来防止这种情况。无论如何,感谢您的提醒。 - Valentin Podkamennyibota
呢?我在其他答案中进行了评论,但是使用此测试用例,您可以看到您只会使用64个字符中的14个字符,这是base64提供的: [...new Set([...Array(100000)].map(()=>btoa(Math.random()).substr(0, 5)).join(""))].sort()
- Or Duan使用es6展开运算符的新版本:
[...Array(30)].map(() => Math.random().toString(36)[2]).join('')
30
是任意数字,您可以选择任何令牌长度36
是您可以传递给numeric.toString()的最大基数,这意味着所有数字和小写字母a-z2
用于选择类似于"0.mfbiohx64i"
的随机字符串中的第三个索引,我们可以在0.
之后取任何索引Array(30).fill().map(() => Math.random().toString(36).slice(2)).join('')
生成一个庞大的随机字符串。 - Hoxz|| '0'
,这样如果 Math.random()
返回 0
(它永远不会返回 1
),它就会回退到 0
而不是 undefined
。 - Juan Campa这样类似的代码应该可以正常工作。
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');
crypto.randomBytes(3).toString('hex')
(例如,3个字节会产生6个字符)。 - Fattiefunction 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));
while(L--)
会完成它。 - vsync'A'.charCodeAt(0)
代替神奇数字55
(同样适用于61
)。特别是在我的平台上,神奇数字返回的是65
。这样代码也更易于自我说明。 - Grumdrig/**
* Pseudo-random string generator
* https://dev59.com/dnM_5IYBdhLWcg3wgja2#27872144
* 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 输出使用了额外的检查,但让我们将其简化为基本要素(仅限字母数字),以获得更好的理解:
var str = "";
,用于连接随机字符0 到 61
的随机索引号(0..9+A..Z+a..z = 62)rand
(因为它是 0..61),通过增加某个数字(参见下面的示例)来获取正确的 CharCode
数字和相关字符。str
上一个 String.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 )
可以得到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 |
上表中的三元条件运算符逻辑:
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))
x.toString(36)
--- 正如上面的答案所使用的那样 --- 在比较具有不同 ES 版本的两个应用程序的输出时,不能可靠地生成相同的字符。而这个函数对我来说解决了这个问题,因为它不使用 .toString()
! - Harley Lang