It is true that your method generates a more or less random string which could be used as a uuid. However, its readability is very bad, in exchange for very short code. Additonally it does not stick to the RFC standards for UUIDS. For an updated solution of your function check out: https://stackoverflow.com/a/2117523/8524465 and for more details on UUIDS: https://stackoverflow.com/a/105074/8524465
However, let's focus especially on your requested line and let me try to explain it step by step.
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
This line defines 2 variables, namely r
and v
. We can easily split this into 2 lines.
var r = Math.random() * 16 | 0;
var v = c == 'x' ? r : (r & 0x3 | 0x8);
Variable Definition 1: (r = Math.random() * 16 | 0;
):
Math.random()
is a function that returns a value between 0
and 1
. (0 inclusive - 1 exclusive) [E.g: 0.36342115]
- By multipling the value with 16, the result is between
0
and 16
. (0 inclusive - 16 exclusive) [E.g: 5.8147384]
- By using the bitwise OR-operator with zero (
| 0
), we basically floor the result, since the number ist cast to an integer. (0 inclusive - 15 inclusive) [E.g: 5]
Without going into too much detail of logic operations, a bitwise or with zero means that no bits are changed. However, since bitwise operations work on 32-bit integers the result is cast and hence floored to an integer. Without too much performance overhead we can replace this action with a dedicated floor function to improve readability. (https://stackoverflow.com/a/7488075/8524465)
All bitwise operations except unsigned right shift, >>>, work on
signed 32-bit integers. So using bitwise operations will convert a
float to an integer.
var r = Math.floor(Math.random() * 16);
Variable Definition 2 (var v = c == 'x' ? r : (r & 0x3 | 0x8);
):
Variable Definition 2.1 (var v = r & 0x3 | 0x8
):
- We know that
r
has a value of either 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,or 15
.
- By using the bitwise AND-operator with
0x3
and the bitwise OR-operator with 0x8
, the result (v
) will have a value of either 8,9,10,11.
- Sidenote: this case will never happen in your method since your string that is replaced only contains the
x
values.
For more information on bitwise operations check out: https://www.w3schools.com/js/js_bitwise.asp
tldr: Just give me a method that returns a UUID in typescript.
Using the @broofa 's newest version (https://stackoverflow.com/a/2117523/8524465) as base:
uuidv4(): string {
// @ts-ignore
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
// tslint:disable-next-line:no-bitwise
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}
For completion: your method, simplified and written in typescript:
generateUniqSerial(): string {
return 'xxxx-xxxx-xxx-xxxx'.replace(/[x]/g, (c) => {
const r = Math.floor(Math.random() * 16);
return r.toString(16);
});
}