用ToString生成验证码、字母序列
想要以更优的算法生成 "1d3ade","9ded19" 之类的验证码么? 想要快速生成"ABCDEFGHIJKL"之类的字母序列么?
通过 toString 的一些"trick",你可以以极简的算法复杂度实现上面的需求。
什么是toString?
其实不想用过多的笔墨介绍toString , 但是如果你真的还不知道什么是toString,那么你可能需要梳理一下你的前端知识了。
toSring 其实有2种形态
1. obj.toString()
所有的obj都有toString方法,大多数的自定义对象会返回[object type]
,当然你也可以自定义修改toString方法达到各种目的。但这并不是今天的目的,想了解更多的话可以通过这个链接 Object.prototype.toString() 查看详细的内容。
2. numObj.toString([radix])
第二种是针对Number
对象的toString,主要的作用是将数字转换成字符串,细节可以参考 Number.prototype.toString() ,但是很多时候,我们会忽略后面的参数radix
。
radix
主要用来指定原始数据的位数,是2-36
之间的整数,那么为什么最大是36呢?看看键盘或许就可以更好的理解了,阿拉伯数字0-9
共10个字符,英文a-z
共26个字符,加在一起正好是36。这就是我们所说的base-36,当然有些情况下会把大写字母A-Z
也算进来,就是我们通常说的base-62,在有些情况下中,base-62用来描述时间戳,例如:
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 |
ok, 啰嗦了一大堆,下面我们进入正题。
用toString()生成随机验证码
如果有这样的一个需求,生成4位验证码,要求每一位是0-9a-z
中的一个,那么你会怎么去实现?
比较笨一点的方法是我们先做一个map表
var map = [0,1,2,3,4,5,6,7,8,9,a,b,c,d,...,x,y,z]
然后在生成4个随机的序列,然后拼成一个验证码
var count = 4;
var code = [];
while(count--) {
var index = Math.random() * 35 | 0;
code.push(map[index])
}
var code = code.join('');
上面的方法我们用for(while)
产生了4个随机数,并且,用了array的join()
去拼凑这些结果(当然了string相加的方法也是可行的)。
其实如果我们很了解toString()的话,可以只用一个随机数,并且可以免去for
以及字符串的拼接,更方便的是你可以完完全全抛弃上面的map
。
首先我们知道0-9a-z
其实就是36位数字的组成,那么问题就变得很简单了,我们生成长度为4位的36位数字,然后转换成string,问题就解决了。
举个栗子
(1231312).toString(36) \\ qe34 (数字1231312对于的36进制的字符)
(642312).toString(36) \\ drm0 (数字642312对于的36进制的字符)
下面就是简单的数学问题了,如果要产生4位的36进制的数字,那么他的范围是 1000
to zzzz
,对应的10进制就是 Math.pow(36,3)
to (Math.pow(36,4)-1)
那么完整的代码入下:
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);
非常简单,2个数字外加一个随机数,就完成了所有的事情。
那么有人要问了,我如果需要改变验证码的长度怎么办?简单,我们来封装一下。
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;
}
ok, 看起来已经很爽了,但是当我们生成7位的数字的时候,你会发现变成一个负数,机智的你一定知道了答案。现在我们来处理这种情况。
function getCode(len) {
len = len || 4;
if (len > 6) {
// 如果大于6位,我们采用生成多组的方法来处理,每组6位
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;
}
}
我们尝试一下
getCode(40) //pvbj7mmri1l1q8x28baqs3sfp4hiczmiyh1pb40v
用toString()生成字母序列
其实如果上面的方法看明白之后,如何生成字母序列就不用我细说了。只要从10开始累加即可。