Generate CAPTCHA, Alphabetical Sequence with ToString

Sorry, this article is not written in English and has not been translated into English yet .You can view this article in English with Google Translate, or please come back later.

想要以更优的算法生成 "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开始累加即可。

60490
  • logo
    • HI, THERE!I AM MOFEI

      (C) 2010-2024 Code & Design by Mofei

      Powered by Dufing (2010-2020) & Express

      IPC证:沪ICP备2022019571号-1