uuid例:18efca2d-6e25-42bf-a636-30b8f9f2de09
代码生成方案(引自文章:面试官问:能否模拟实现JS的call和apply方法)
let random
let uuid = ''
for (let i = 0; i < 32; i++) {
random = Math.random() * 16 | 0; // 解释1
if (i === 8 || i === 12 || i === 16 || i === 20) { // 解释2
uuid += '-';
}
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16); // 解释3
}
return uuid;
解释:
-
random = Math.random() * 16 | 0
是为了去除随机数生成的小数,因为位运算只对整数有效,遇到小数时,会将小数部分舍去,只保留整数部分 - uuid第8、12、16、20位都是连字符
-
- uuid格式
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
- 数字 M的四位表示 UUID 版本,当前规范有5个版本,M可选值为1, 2, 3, 4, 5
- 代码中
i === 12 ? 4 : xxx
,需要生成的M为4,因为第四个版本是根据随机数生成 - 数字 N的一至四个最高有效位表示 UUID 变体( variant ),有固定的两位10xx因此只可能取值8, 9, a, b
- 代码中
i === 16 ? (random & 3 | 8) : xxx
这里是为了保证数字N有固定的两位10xx,首先random & 3
,3的二进制为0011,与操作符&
将random
前两位置0,后两位不变,然后random & 3 | 8
,9的二进制为1000,或操作符|
将random
最高位置1,这样一通操作可以保证random
前两位为10后两位不变 - 因为uuid每一位都是十六进制数,因此我们通过
toString(16)
传参将每一位进行十六进制转化。