Do you want to generate verification codes like "1d3ade" and "9ded19" with a better algorithm?
Do you want to quickly generate letter sequences like "ABCDEFGHIJKL"?
By using some "tricks" of toString, you can achieve the above requirements with an extremely simple algorithmic complexity.
I don't want to spend too much time introducing toString, but if you really don't know what toString is, then you might need to brush up on your front-end knowledge.
There are actually two forms of toString.
All objects have a toString method, and most custom objects will return [object type]
. Of course, you can also customize the toString method to achieve various purposes. But this is not the purpose of today's topic; if you want to learn more, you can refer to this link Object.prototype.toString() for detailed content.
The second form is the toString method for the Number
object, primarily used to convert numbers to strings. For details, you can refer to Number.prototype.toString(), but many times, we overlook the radix
parameter.
radix
is mainly used to specify the base of the original data, which is an integer between 2-36
. So why is the maximum 36? You might better understand this by looking at a keyboard: there are a total of 10 Arabic numeral characters 0-9
, plus 26 English characters a-z
, adding up to exactly 36. This is what we call base-36. Of course, in some cases, uppercase letters A-Z
are also included, which is what we commonly refer to as base-62. In some instances, base-62 is used to describe timestamps, for example:
Date (UTC) | Base 62 epoch |
---|---|
1970-06-21 00:32:16 | 10000 |
1975-01-01 00:00:00 | AfyFM |
1980-01-01 00:00:00 | LLwUi |
2015-01-01 00:00:00 | 1Y6TBI |
2020-01-01 00:00:00 | 1imRQe |
Okay, having rambled on, let's get to the point.
If there's a need to generate a 4-digit verification code, where each digit is one of 0-9a-z
, how would you implement it?
A rather clumsy method would be to create a map table first.
var map = [0,1,2,3,4,5,6,7,8,9,a,b,c,d,...,x,y,z]
Then generate 4 random sequences and concatenate them into a verification code.
var count = 4;
var code = [];
while(count--) {
var index = Math.random() * 35 | 0;
code.push(map[index])
}
var code = code.join('');
In the above method, we used for(while)
to produce 4 random numbers and concatenated these results using the array's join()
(of course, string concatenation is also viable).
If we are very familiar with toString(), we can achieve this using just a random number and eliminate the for
loop and string concatenation, and even entirely discard the above map
.
First, we know that 0-9a-z
actually constitutes 36 digits. Therefore, the question becomes very simple: we generate a number in the range of 4 digits in base-36 and convert it to a string, which solves our problem.
For example:
(1231312).toString(36) \ qe34 (The number 1231312 corresponds to its base-36 character)
(642312).toString(36) \ drm0 (The number 642312 corresponds to its base-36 character)
Now it's a simple math problem. To produce a 4-digit base-36 number, its range is 1000
to zzzz
, corresponding to decimal values of Math.pow(36,3)
to (Math.pow(36,4)-1)
.
So, the complete code is as follows:
var start = Math.pow(36,3);
var end = (Math.pow(36,4)-1);
var number = start + Math.random()*(end-start) | 0;
var code = number.toString(36);
Very simple! With just 2 numbers plus one random number, everything is done.
Now some may ask, what if I need to change the length of the verification code? Simple, let's encapsulate it.
function getCode(len) {
len = len || 4;
var start = Math.pow(36,len-1);
var end = (Math.pow(36,len)-1);
var number = start + Math.random()*(end-start) | 0;
var code = number.toString(36);
return code;
}
Okay, this looks pretty good, but when we generate a 7-digit number, you will find it becomes a negative number. Surely, you are smart enough to know the answer. Now let's handle this situation.
function getCode(len) {
len = len || 4;
if (len > 6) {
// If more than 6 digits, we generate multiple groups, each group 6 digits.
var time = len/6|0;
var lastNum = len%6;
var code = [];
for(var i=0; i<time; i++){
code.push(generate(6));
}
if (lastNum) {
code.push(generate(lastNum));
}
return code.join('');
}else{
return generate(len);
}
function generate(len) {
var start = Math.pow(36,len-1);
var end = (Math.pow(36,len)-1);
var number = start + Math.random()*(end-start) | 0;
var code = number.toString(36);
return code;
}
}
Let's give it a try.
getCode(40) //pvbj7mmri1l1q8x28baqs3sfp4hiczmiyh1pb40v
Actually, once you understand the above method, generating letter sequences is also straightforward; just start accumulating from 10.