用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开始累加即可。

Write a response...
Mofei Zhu
publish
剧中人
2015-11-06 10:41
配合 Math的随机数和Date生成的时间戳,可以模拟出很多有意思的字符串串出来!
1
 Replay
@剧中人  
Replay
yoom
2015-11-03 10:28
@yoom function abc(length){ var str=(987654321123456789).toString(36).split('').sort(function(a,b){return Math.random()-0.5}).join('') return str.substring(0,length) }
1
 Replay
@yoom  
Replay
yoom
2015-11-03 10:26
(987654321123456789).toString(36).split('').sort(function(a,b){return Math.random()-0.5}).join('')
0
 Replay
@yoom  
Replay