我想要一个由从集合中随机挑选的字符组成的 5 个字符串[a-zA-Z0-9]
。
使用 JavaScript 执行此操作的最佳方法是什么?
我想要一个由从集合中随机挑选的字符组成的 5 个字符串[a-zA-Z0-9]
。
使用 JavaScript 执行此操作的最佳方法是什么?
我认为这对你有用:
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));
//Can change 7 to 2 for longer results.
let r = (Math.random() + 1).toString(36).substring(7);
console.log("random", r);
注意:上述算法有以下缺点:
Math.random()
可能会产生可预测的(“随机外观”但不是真正随机的)输出,具体取决于实现。当您需要保证唯一性或不可预测性时,结果字符串不适合。选项1
如果您能够在服务器端执行此操作,只需使用加密module -
var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');
// "bb5dc8842ca31d4603d6aa11448d1654"
生成的字符串将是您生成的随机字节的两倍;编码为十六进制的每个字节是 2 个字符。20 个字节将是 40 个十六进制字符。
选项 2
如果您必须执行此客户端,请尝试使用 uuid module -
var uuid = require("uuid");
var id = uuid.v4();
// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"
选项 3
如果您必须在客户端执行此操作并且不必支持旧浏览器,则可以在没有依赖项的情况下执行此操作 -
// 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"
有关更多信息crypto.getRandomValues
-
该
crypto.getRandomValues()
方法可让您获得加密强随机值。作为参数给出的数组填充有随机数(随机在其加密含义中)。
这是一个小控制台示例 -
> 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
正好返回 5 个随机字符,而不是此处找到的一些评分最高的答案。
Math.random().toString(36).substr(2, 5);
这是对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)
解释:
进一步的想法:
更新:
这是我想出的其他几种功能风格的单衬。它们与上述解决方案的不同之处在于:
所以,假设你选择的字母是
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' 以减少更多字节。