你的方法确实生成了一个可以用作uuid的更或多少随机的字符串。但是,它的可读性非常差,换来的是非常简短的代码。此外,它不符合UUIDS的RFC标准。要获取功能更新的解决方案,请查看:
https://dev59.com/7HVD5IYBdhLWcg3wDXF3#2117523 。有关UUIDS的更多详细信息,请访问:
https://dev59.com/7HVD5IYBdhLWcg3wDXF3#105074
然而,我们特别关注你请求的行,并让我一步一步地尝试解释它。
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
这行代码定义了两个变量,分别是r
和v
。我们可以很容易地将其拆分为两行。
var r = Math.random() * 16 | 0;
var v = c == 'x' ? r : (r & 0x3 | 0x8);
变量定义 1: (r = Math.random() * 16 | 0;
):
Math.random()
是一个返回值介于 0
和 1
之间的函数。 (包括 0,但不包括 1) [例如:0.36342115]
- 将该值乘以 16,得到介于
0
和 16
之间的结果。 (包括 0,但不包括 16) [例如:5.8147384]
- 通过使用按位或运算符和零 (
| 0
),我们基本上对结果进行了向下取整,因为数字被转换为整数。(包括 0 - 包括 15) [例如:5]
不详细解释逻辑运算,与零进行按位或的意思是没有位被更改。但是,由于按位操作是在32位整数上进行的,因此结果会被转换并因此向下取整为整数。为了提高可读性而不会带来太多性能开销,可以使用专门的 floor 函数代替此操作。(https://dev59.com/Lms05IYBdhLWcg3wCNlG#7488075)
除了无符号右移(>>>)以外,所有按位操作都适用于带符号的32位整数。因此,使用按位操作会将浮点数转换为整数。
var r = Math.floor(Math.random() * 16);
变量定义2 (var v = c == 'x' ? r : (r & 0x3 | 0x8);
):
如果c等于'x',则v等于r的值,否则v等于r按位与0x3后再或0x8的值。
变量定义 2.1 (var v = r & 0x3 | 0x8
):
- 我们知道
r
的值可以是0,1,2,3,4,5,6,7,8,9,10,11,12,13,14或者15
。
- 通过位与运算符使用
0x3
和位或运算符使用0x8
,结果(v
)将具有8,9,10,11
中的一个值。
- 注:由于要替换的字符串中只包含
x
值,因此您的方法不会发生这种情况。
有关位运算的更多信息,请查看:https://www.w3schools.com/js/js_bitwise.asp
tldr: 只需给我一个在typescript中返回UUID的方法即可。
基于@broofa的最新版本(https://dev59.com/7HVD5IYBdhLWcg3wDXF3#2117523):
uuidv4(): string {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
完整的方法,简化版并用 TypeScript 编写:
generateUniqSerial(): string {
return 'xxxx-xxxx-xxx-xxxx'.replace(/[x]/g, (c) => {
const r = Math.floor(Math.random() * 16);
return r.toString(16);
});
}