Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

generate Random uuid Javascript

I'm trying to build a function to generate a random uuid, I found some thing on stack and I need to understand a little bit how that function work to create it with typescript :

public generateUniqSerial() {
    return 'xxxx-xxxx-xxx-xxxx'.replace(/[x]/g, function (c) {
      var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  }

is that writen good in es6 and can you help to understand how that line works :

var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
like image 851
sahnoun Avatar asked Jul 22 '26 05:07

sahnoun


2 Answers

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. Additionally, 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 multiplying 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 is cast to an integer. (0 inclusive - 15 inclusive) [E.g: 5] Without going into too much detail about 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);):

  • Here a ternary operator is used to keep the required code short for the assignment.
    var (variableName) = (condition) ? (valueIfConditionIsTrue) : (valueIfConditionIsFalse);
    
    This could be rewritten with a simple if/else-statement.
    var v = "";
    if (c === 'x') { 
        v = r;
    }
    else {
        v = 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);  
  });  
}
like image 125
Daniel Metzner Avatar answered Jul 24 '26 19:07

Daniel Metzner


Here is a totally non-compliant but very performant implementation to generate an ASCII-safe GUID-like unique identifier.

function generateGuid() {
return Math.random().toString(36).substring(2, 15) +
    Math.random().toString(36).substring(2, 15);
}

Generates 26 [a-z0-9] characters, yielding a UID that is both shorter and more unique than RFC compliant GUIDs.

Note: Any UUID generator that relies on Math.random() is not strongly, because it does not provide good uniqueness guarantees.

like image 35
Efrat Ifergan Avatar answered Jul 24 '26 17:07

Efrat Ifergan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!