JavaScript 开发笔记

1. 基本操作

1.1. Date/Time

1.1.1. 转换UTC时间

function ConvertUtcTime(utctime, style) {
    if (utctime == null || utctime == "") {
        return "";
    }else {
        var d = utctime.substring(6, utctime.length - 1);
        var newdate = new Date(parseInt(d));
        if (style == null || style == "") style = "yyyy-MM-dd hh:mm:ss";
        return newdate.format(style);
    }
}

1.1.2. 将日期转换为yyyymmddhhssmm格式

function getDate(date) {
    var year = date.getFullYear();

    var month = date.getMonth() + 1;
    var date1 = date.getDate();
    var day = date.getDay();

    var hours = date.getHours();

    var minutes = date.getMinutes();
    var seconds = date.getSeconds();
    var ms = date.getMilliseconds();
    var curDateTime = year;
    if (month > 9) {
        curDateTime = curDateTime + month;
    } else {
        curDateTime = curDateTime + "0" + month;
    }
    if (day > 9) {
        curDateTime = curDateTime + day;
    } else {
        curDateTime = curDateTime + "0" + day;
    }
    if (hours > 9) {
        curDateTime = curDateTime + "" + hours;
    } else {
        curDateTime = curDateTime + "0" + hours;
    }
    if (minutes > 9) {
        curDateTime = curDateTime + minutes;
    } else {
        curDateTime = curDateTime + "0" + minutes;
    }
    if (seconds > 9) {
        curDateTime = curDateTime + seconds;
    } else {
        curDateTime = curDateTime + "0" + seconds;
    }
    return curDateTime;
}

1.1.3. 格式化日期

Date.prototype.format = function (format) {
    var o =
        {
            "M+": this.getMonth() + 1, //month
            "d+": this.getDate(),    //day
            "h+": this.getHours(),   //hour
            "m+": this.getMinutes(), //minute
            "s+": this.getSeconds(), //second
            "q+": Math.floor((this.getMonth() + 3) / 3),  //quarter
            "S": this.getMilliseconds() //millisecond
        }
    if (/(y+)/.test(format))
        format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
        if (new RegExp("(" + k + ")").test(format))
            format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
    return format;
}

1.1.4. 日期加减

function DateAdd(dateObj, days) {
    var tempDate = dateObj.valueOf();
    tempDate = tempDate + days * 24 * 60 * 60 * 1000
    tempDate = new Date(tempDate)
    return tempDate;
}

1.1.5. 获取指定日期

//获取指定日期开始时间(00:00:00)
function getTodayStart(date) {
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    var d = date.getDate();
    var time = y + '-' + (m < 10 ? ('0' + m) : m) + '-' + (d < 10 ? ('0' + d) : d) + " 00:00:00";
    return time;
}

//获取指定日期结束时间(00:00:00)
function getTodayEnd(date) {
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    var d = date.getDate();
    var time = y + '-' + (m < 10 ? ('0' + m) : m) + '-' + (d < 10 ? ('0' + d) : d) + " 23:59:59";
    return time;
}

//获取指定当月第一天日期
function getMonthStart(date) {
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    //var d = date.getDate();
    var time = y + '-' + (m < 10 ? ('0' + m) : m) + '-' + 1;
    return time;
}

//获取指定当天日期
function getMonthEnd(date) {
    var y = date.getFullYear();
    var m = date.getMonth() + 1;
    var d = date.getDate();
    var time = y + '-' + (m < 10 ? ('0' + m) : m) + '-' + (d < 10 ? ('0' + d) : d);
    return time;
}

//获取月份最后一天
function getCurrentMonthLast(date) {
    var currentMonth = date.getMonth();
    var nextMonth = ++currentMonth;
    var nextMonthFirstDay = new Date(date.getFullYear(), nextMonth, 1);
    var oneDay = 1000 * 60 * 60 * 24;
    return new Date(nextMonthFirstDay - oneDay);
}

1.1.6. 计算日期差

function getDateDiff(date1, date2) {
    var times = date2 - date1;
    var days = Math.floor(times / (1000 * 60 * 60 * 24));
    times = times - days * 1000 * 60 * 60 * 24;
    var hours = Math.floor(times / (1000 * 60 * 60));
    times = times - hours * 1000 * 60 * 60;
    var minus = Math.floor(times / 60000);
    times = times - minus * 60000;
    var secs = Math.floor(times / 6000);

    var ret = "";
    if (days > 0) {
        ret = days + "天" + hours + "时" + minus + "分" + secs + "秒";
    }
    else {
        if (hours > 0) ret = hours + "时";
        ret = ret + minus + "分" + secs + "秒";
    }
    return ret;
}

1.1.7. 指定睡眠时间

/**
 * js指定睡眠时长
 * @param  {[type]} numberMillis [description]
 * @return {[type]}              [description]
 */
function sleep(numberMillis) {
    var now = new Date();
    var exitTime = now.getTime() + numberMillis;
    while (true) {
        now = new Date();
        if (now.getTime() > exitTime)
            return;
    }
}

1.1.8. 倒计时

<strong>剩余时间:</strong><span id="timer"></span>

//倒计时 start
var time_end,time_now_server,time_now_client,time_end,time_server_client,timerID;
//截止时间
time_end = new Date('{$appraisal_points.stop_time|date="Y-m-d H:i:s",###}');
time_end=time_end.getTime();
//当前时间
time_now_server=new Date();
time_now_server=time_now_server.getTime();
time_now_client=new Date();
time_now_client=time_now_client.getTime();
time_server_client=time_now_server-time_now_client;
setTimeout("show_time()",1000);
//显示时间函数
function show_time()
{
    Var timer = document.getElementById("timer");
    if(!timer){
        return ;
    }
    timer.innerHTML =time_server_client;

    var time_now,time_distance,str_time;
    var int_day,int_hour,int_minute,int_second;
    var time_now=new Date();
    time_now=time_now.getTime()+time_server_client;
    time_distance=time_end-time_now;
    if(time_distance>0)
    {
        int_day=Math.floor(time_distance/86400000);
        time_distance-=int_day*86400000;
        int_hour=Math.floor(time_distance/3600000);
        time_distance-=int_hour*3600000;
        int_minute=Math.floor(time_distance/60000);
        time_distance-=int_minute*60000;
        int_second=Math.floor(time_distance/1000);

        if(int_hour<10){
            int_hour="0"+int_hour;
        }
        if(int_minute<10){
            int_minute="0"+int_minute;
        }
        if(int_second<10){
            int_second="0"+int_second;
        }
        if (int_day>0) {
            str_time="<b style='color:#46be8a;'>"+int_day+"</b style='color:#46be8a;'>天<b style='color:#46be8a;'>"+int_hour+"</b style='color:#46be8a;'>小时<b style='color:#46be8a;'>"+int_minute+"</b style='color:#46be8a;'>分钟<b style='color:#46be8a;'>"+int_second+"</b style='color:#46be8a;'>秒";
        }else if(int_day == 0 && int_hour>=12){
            str_time="<b style='color:#f5a751;'>"+int_day+"</b style='color:#f5a751;'>天<b style='color:#f5a751;'>"+int_hour+"</b style='color:#f5a751;'>小时<b style='color:#f5a751;'>"+int_minute+"</b style='color:#f5a751;'>分钟<b style='color:#f5a751;'>"+int_second+"</b style='color:#f5a751;'>秒";
        }else if(int_day == 0 && int_hour<=5){
            str_time="<b style='color:#fc6167;'>"+int_day+"</b style='color:#fc6167;'>天<b style='color:#fc6167;'>"+int_hour+"</b style='color:#fc6167;'>小时<b style='color:#fc6167;'>"+int_minute+"</b style='color:#fc6167;'>分钟<b style='color:#fc6167;'>"+int_second+"</b style='color:#fc6167;'>秒";
        }
        timer.innerHTML=str_time;
        setTimeout("show_time()",1000);
    }
    else
    {
        timer.innerHTML =timer.innerHTML;
        clearTimeout(timerID);
        // window.location.href="http://www.baidu.com";
    }
}
//倒计时 end

1.2. String

1.2.1. 常用内置函数

  concat(str1,str2),字符串拼接
  left(str, length),
  right(str, length),
  substring(str, pos, length[optional]),pos:从第几位开始截取
  mid(),
  substr(),
  substring_index(str, delim, count),delim:关键字,count:关键字出现的次数
#+END_SRC*** 生成随机验证码
#+BEGIN_SRC javascript
  function CreateCode() {
      var code = '';
      var codeLength = 6;//验证码的长度
      var selectChar = new Array('1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');

      for (var i = 0; i < codeLength; i++) {
          var charIndex = Math.floor(Math.random() * 32);
          code += selectChar[charIndex];
      }
      return code;
  }

1.2.2. 截取字符串包含中文处理

//(串,长度,增加...)
function subString(str, len, hasDot) {
    var newLength = 0;
    var newStr = "";
    var chineseRegex = /[^\x00-\xff]/g;
    var singleChar = "";
    var strLength = str.replace(chineseRegex, "**").length;
    for (var i = 0; i < strLength; i++) {
        singleChar = str.charAt(i).toString();
        if (singleChar.match(chineseRegex) != null) {
            newLength += 2;
        }
        else {
            newLength++;
        }
        if (newLength > len) {
            break;
        }
        newStr += singleChar;
    }

    if (hasDot && strLength > len) {
        newStr += "...";
    }
    return newStr;
}

1.2.3. 获取 url 参数

function GetRequest() {
    var url = location.search; //获取url中"?"符后的字串
    var theRequest = new Object();
    if (url.indexOf("?") != -1) {
        var str = url.substr(1);
        strs = str.split("&");
        for (var i = 0; i < strs.length; i++) {
            theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
        }
    }
    return theRequest;
}

1.2.4. 数字显示千分位

// 数字转换为千分位显示
function numberToThousands(number){
    var reg = /\d{1,3}(?=(\d{3})+$)/g;
    return number.toString().replace(reg, function(str){
        return str + ',';
    });
}
// 千分位转换为数字
function thousandsToNumber(numberThousand){
    return parseInt(numberThousand.toString().split(',').join(''));
}

1.3. Math/Number

1.3.1. 默认返回 0 ~ 1 之间的随机数

// 取得介于 1 到 10 之间的一个随机数:
Math.floor((Math.random()*10)+1);
// 返回 min(包含)~ max(包含)之间的数字:
function getRndInteger(min, max) {
    return Math.floor(Math.random() * (max - min + 1) ) + min;
}

1.3.2. 保留2位小数

  • 四舍五入

    // toFixed()
    // 保留两位小数,将数值类型的数据改变成了字符串类型
    var num =2.446242342;  
    num = num.toFixed(2); 
    console.log(num); //2.45
    console.log(typeof num); // string
    
    // Math.floor()
    // 不四舍五入,向下取整,不改变数据类型
    num = Math.floor(num * 100) / 100;
    console.log(num); //2.44
    console.log(typeof num); // number
    
    // 字符串匹配
    // 先将数据转换为字符串,最后再转为数值类型
    num = Number(num.toString().match(/^\d+(?:\.\d{0,2})?/));
    console.log(num); //2.44
    console.log(typeof num); // number
    
    // 四舍五入保留2位小数(若第二位小数为0,则保留一位小数)
    // 数据类型不变
    function keepTwoDecimal(num) {
        var result = parseFloat(num);
        if (isNaN(result)) {
            alert('传递参数错误,请检查!');
            return false;
        }
        result = Math.round(num * 100) / 100;
        return result;
    };
    keepTwoDecimal(num);
    console.log(num); //2.44
    console.log(typeof num); //number
    
    // 四舍五入保留2位小数(不够位数,则用0替补
    // 数据类型变为字符串类型
    function keepTwoDecimalFull(num) {
        var result = parseFloat(num);
        if (isNaN(result)) {
            alert('传递参数错误,请检查!');
            return false;
        }
        result = Math.round(num * 100) / 100;
        var s_x = result.toString(); //将数字转换为字符串
        var pos_decimal = s_x.indexOf('.'); //小数点的索引值
    
        // 当整数时,pos_decimal=-1 自动补0
        if (pos_decimal < 0) {
            pos_decimal = s_x.length;
            s_x += '.';
        }
    
        // 当数字的长度< 小数点索引+2时,补0
        while (s_x.length <= pos_decimal + 2) {
            s_x += '0';
        }
        return s_x;
    }
    
    console.log(keepTwoDecimalFull(120.5)); //120.50
    console.log(typeof keepTwoDecimalFull(120.5)); //string
    console.log(keepTwoDecimalFull(2.446242342)); //2.45
    console.log(typeof keepTwoDecimalFull(2.446242342)); //string
    
  • 浮点数保留两位小数

    //浮点数保留两位小数
    //1.功能:将浮点数四舍五入,取小数点后2位
    function toDecimal(x) {
        var f = parseFloat(x);
        if (isNaN(f)) {
            return;
        }
        f = Math.round(x*100)/100;
        return f;
    }
    console.log(toDecimal(3.1465926)); // 3.15
    console.log(typeof toDecimal(3.1415926)); //number
    
    //2.强制保留2位小数,如:2,会在2后面补上00.即2.00
    function toDecimal2(x) {
        var f = parseFloat(x);
        if (isNaN(f)) {
            return false;
        }
        var f = Math.round(x*100)/100;
        var s = f.toString();
        var rs = s.indexOf('.');
        if (rs < 0) {
            rs = s.length;
            s += '.';
        }
        while (s.length <= rs + 2) {
            s += '0';
        }
        return s;
    }
    console.log(toDecimal2(3.1)); // 3.10
    console.log(typeof toDecimal2(3.1415926)); //string
    
    
    // 3.保留两位小数 浮点数四舍五入 位数不够 不补0
    function fomatFloat(src,pos){
        return Math.round(src*Math.pow(10, pos))/Math.pow(10, pos);
    }
    console.log(fomatFloat(3.12645,2)); // 3.13
    console.log(typeof fomatFloat(3.1415926)); //number
    
  • 直接取整(不考虑小数点后的部分)

    // 方式一: parseInt()
    var n = parseInt("3.14"); //3
    var n = parseInt("-3.14"); //-3
    var n = parseInt("2019hello"); //2019
    var n = parseInt(""); //NaN
    var n = parseInt("0xA"); //10(十六进制)
    var n = parseInt("070"); //56(八进制)
    // 方式二: 位运算
    var n = ~~3.14 //3
    var n = 3.14^0 //3
    var n = 3.14<<0 //3
    
  • 计算后取整(四舍五入,向上取整,向下取整)

    // 四舍五入
    var n = Math.round(3.14); //3
    var n = Math.ceil(8.54); //9
    // 向上取整
    var n = Math.ceil(3.14); //4
    // 向下取整
    var n = Math.ceil(3.14); //3
    

1.4. Array

1.4.1. 判断某元素是否存在数组中

var arr = ['a,','b','c','d','e'];
if(arr.indexOf('a') >= 0) // indexOf 如果元素存在于数组中,会返回数组下标,否则返回 -1
if($.inArray('a',arr) >=0) // 使用 jQuery 的 inArray 方法,与 indexOf 一样,如果元素存在于数组中,会返回数组下标,否则返回 -1

1.5. Object

1.5.1. 对象(Object) ⇋ 字符串(String)

// Object to String
var str=JSON.stringify(obj);
// JSON String to Object
var obj = JSON.parse(str);

1.5.2. 判断对象/数组中key是否存在

if(obj.hasOwnProperty(key)){...}

1.5.3. 数组对象遍历操作

  1. 使用 Object.keys(obj) 遍历

    var obj = {'0':'a','1':'b','2':'c'};
    Object.keys(obj).forEach(function(key){
    console.log(key,obj[key]);
    });
    // 注意: forEach不支持以下2种方式跳出循环,
    // 1) break; 执行报错: Uncaught SyntaxError: Illegal break statement
    // 2) return false; 只能跳出当前遍历执行
    
    // 返回指定格式数组
    var obj = {"1":5,"2":7,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0};
    var result = Object.keys(obj).map(function(key) {
    return [Number(key), obj[key]];
    });
    console.log(result);
    // [[1,5],[2,7],[3,0],[4,0]…].
    
    // 缺失需要跳出循环,使用 try…catch…
    var obj = {'0':'a','1':'b','2':'c'};
    try {
    Object.keys(obj).forEach(function(key){
    if(key == 'a'){
    console.log(key,obj[key]);
    throw new Error('exist');
    }
    });
    } catch (ex) {
    if(ex.message=='exist') throw ex
    } finally {
    console.log('done');
    }
    
  2. for-in

    var obj = {'0':'a','1':'b','2':'c'};
    for(var i in obj) {
        console.log(i,":",obj[i]);
    }
    
  3. for-of

    // 支持数组遍历、大多数类数组对象、字符串(视为一系列的Unicode字符来进行遍历)
    var arr=["张三","李四","王五","赵六"];
    for (var value of arr){
        console.log(value);
    }
    
  4. 使用Object.getOwnPropertyNames(obj) 遍历

    var obj = {'0':'a','1':'b','2':'c'};
    Object.getOwnPropertyNames(obj).forEach(function(key){
        console.log(key,obj[key]);
    });
    
  5. 使用Reflect.ownKeys(obj) 遍历

    var obj = {'0':'a','1':'b','2':'c'};
    Reflect.ownKeys(obj).forEach(function(key){
        console.log(key,obj[key]);
    });
    

2. 校验

2.1. 检查对象是否为空对象

/*
 * 检测对象是否是空对象(不包含任何可读属性)。 //如你上面的那个对象就是不含任何可读属性
 * 方法只既检测对象本身的属性,不检测从原型继承的属性。
 */
function isOwnEmpty(obj) {
    for (var name in obj) {
        if (obj.hasOwnProperty(name)) {
            return false;
        }
    }
    return true;
}
/*
 * 检测对象是否是空对象(不包含任何可读属性)。
 * 方法既检测对象本身的属性,也检测从原型继承的属性(因此没有使hasOwnProperty)。
 */
function isEmpty(obj) {
    for (var name in obj) {
        return false;
    }
    return true;
}

2.2. 身份证号校验

//检验身份证号码

function checkIdcard(idcard) {
    var Msgs = new Array(
        "验证通过",
        "校验身份证号码位数不对,请正确输入身份证号码。",
        "校验出生日期无效,请正确输入真实的身份证号码。",
        "检验身份证号码错误,请输入真实的身份证号码。",
        "校验身份证省份错误,请输入真实的身份证号码。",
        "身份证号码不允许为空,请输入真实的身份证号码。"
    );

    idcard = idcard.toUpperCase();
    var area = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外" }
    var idcard, Y, JYM;
    var S, M;
    var idcard_array = new Array();
    idcard_array = idcard.split("");

    //验证是否为空
    if (idcard.length <= 0) {
        return Msgs[5];
    }

    //验证号码位数
    if (idcard.length != 15 && idcard.length != 18) {
        return Msgs[1];
    }

    //地区检验
    if (area[parseInt(idcard.substr(0, 2))] == null) {
        return Msgs[4];
    }


    //身份号码位数及格式检验
    switch (idcard.length) {
    case 15:
        if ((parseInt(idcard.substr(6, 2)) + 1900) % 4 == 0 || ((parseInt(idcard.substr(6, 2)) + 1900) % 100 == 0 && (parseInt(idcard.substr(6, 2)) + 1900) % 4 == 0)) {
            ereg = /^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$/;//测试出生日期的合法性
        } else {
            ereg = /^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$/;//测试出生日期的合法性
        }
        if (ereg.test(idcard))
            return Msgs[0];
        else {
            return Msgs[3];
        }
        break;
    case 18:
        //18位身份号码检测
        //出生日期的合法性检查
        //闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
        //平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
        if (parseInt(idcard.substr(6, 4)) % 4 == 0 || (parseInt(idcard.substr(6, 4)) % 100 == 0 && parseInt(idcard.substr(6, 4)) % 4 == 0)) {
            ereg = /^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$/;//闰年出生日期的合法性正则表达式
        } else {
            ereg = /^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$/;//平年出生日期的合法性正则表达式
        }
        if (ereg.test(idcard)) {//测试出生日期的合法性
            //计算校验位
            S = (parseInt(idcard_array[0]) + parseInt(idcard_array[10])) * 7
                + (parseInt(idcard_array[1]) + parseInt(idcard_array[11])) * 9
                + (parseInt(idcard_array[2]) + parseInt(idcard_array[12])) * 10
                + (parseInt(idcard_array[3]) + parseInt(idcard_array[13])) * 5
                + (parseInt(idcard_array[4]) + parseInt(idcard_array[14])) * 8
                + (parseInt(idcard_array[5]) + parseInt(idcard_array[15])) * 4
                + (parseInt(idcard_array[6]) + parseInt(idcard_array[16])) * 2
                + parseInt(idcard_array[7]) * 1
                + parseInt(idcard_array[8]) * 6
                + parseInt(idcard_array[9]) * 3;
            Y = S % 11;
            M = "F";
            JYM = "10X98765432";
            M = JYM.substr(Y, 1);//判断校验位
            if (M == idcard_array[17])
                return Msgs[0];
            else {
                return Msgs[3];
            }
        }
        else {
            return Msgs[2];
        }
        break;
    default:
        return Msgs[1];
        break;
    }
}

//身份证号码验证算法

//--根据17位数字本体码获取最后一位校验码程序
public class Id18 {
    int[] weight={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};    //十七位数字本体码权重
    char[] validate={ '1','0','X','9','8','7','6','5','4','3','2'};    //mod11,对应校验码字符值

    public char getValidateCode(String id17){
        int sum = 0;
        int mode = 0;
        for(int i = 0; i < id17.length(); i++){
            sum=sum+Integer.parseInt(String.valueOf(id17.charAt(i)))*weight[i];
        }
        mode = sum % 11;
        return validate[mode];
    }

    public static void main(String[] args){
        Id18 tes t= new Id18();
        System.out.println("该身份证验证码:"+test.getValidateCode("14230219700101101"));    //该身份证校验码:3
    }
}

公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。
排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码。

  1. 地址码
    表示编码对象常住户口所在县(市、旗、区)的行政区域划分代码,按GB/T2260的规定执行。
  2. 出生日期码
    表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。
  3. 顺序码
    表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
  4. 校验码计算步骤
    (1)十七位数字本体码加权求和公式
    S = Sum(Ai * Wi), i = 0, … , 16 ,先对前 17 位数字的权求和
    Ai:表示第i位置上的身份证号码数字值(0~9)
    Wi:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 (表示第 i 位置上的加权因子)
    (2)计算模
    Y = mod(S, 11)
    (3)根据模,查找得到对应的校验码
    Y: 0 1 2 3 4 5 6 7 8 9 10
    校验码: 1 0 X 9 8 7 6 5 4 3 2
  5. 说明:
    • 程序可以根据已有的17位数字本体码,获取对应的验证码。
    • 该程序可以剔除验证码不正确的身份证号码。
    • 15位的身份证出生年份采用年份后2位,没有最后1位校验码。
    • 完整的身份证18位,最后一位校验位可能是非数字。我们的一个项目,数据库保存前17位数字,这样对应一些SQL语句(比如inner join)有加速作用的!!!

2.3. 电话号码校验


2.4. Email校验


2.5. IP地址校验


2.6. 其他校验

2.6.1. 检查QQ号码

function checkqq()  //检查QQ号码
{
    var qq=document.getElementById("qq").value;
    var divqq=document.getElementById("qq");
    if(qq!="")
    {
        if(qq.match(/\D/)!=null)
        {
            divqq.innerHTML="<font color='red'>QQ号码只能输入数字!</font>";
            return false;
        }
        else
        {
            divqq.innerHTML="<font color='red'>√</font>";
            return true;
        }
    }
    else
    {
        divqq.innerHTML="<font color='green'>√</font>";
        return true;
    }
}

3. 页面交互

3.1. JavaScript 与 URL

// 打开新标签页
window.open("http://www.baidu.com");
window.open("http://www.baidu.com","_blank");
// 打开新窗口
window.open("http://www.baidu.com","_blank","");
// 在当前页面中打开链接
window.open("http://www.baidu.com","_self","");
window.location.href="http://www.baidu.com";

// 跳转文件下载页面时,出现空白页
// A:使用 js 出发 <a> 标签事件
var downLoad=function(src){
    var a = document.createElement('a');
    a.id = 'expertFile'
    a.href =src;
    document.body.append(a); 
    a.click();
    document.getElementById('expertFile').remove();
}
// B:通过 iframe 来下载
function  download (src) {
    var download_file= {} 
    if (typeof(download_file.iframe) == "undefined") {
        var iframe = document.createElement("iframe");
        download_file.iframe = iframe;
        document.body.appendChild(download_file.iframe);
    }
    download_file.iframe.src = src
    download_file.iframe.style.display = "none";
}

3.2. 根据网页实际大小来设置iframe显示区域大小

$('#iframe_i').load(function () {
    // “ref_page”为引用页面DIV的ID,获取DIV的外部宽度、外部高度。
    var width = $(this).contents().find('#ref_page').outerWidth();
    var height = $(this).contents().find('#ref_page').outerHeight();
    // 设置iframe的宽度、高度。
    $(this).width(width);
    $(this).height(height);
)};

3.3. 动态显示收缩列表

$(document).ready(function(){
    //当点击某一列表项时,滑出下级菜单并收起其他列表项
    $("#user_manage").click(function(){
        // $("#user_about").fadeToggle();
        $("#user_manage").addClass("active");
        $("#node_manage").removeClass("active");
        $("#role_manage").removeClass("active");
        $("#setting").removeClass("active");
        $("#user_about").slideToggle();
        $("#node_about").slideUp();
        $("#role_about").slideUp();
        /*$("#div2").fadeToggle("slow");
          $("#div3").fadeToggle(3000);*/
    });
});
https://jqueryui.com/accordion/

3.4. 滚动到页面顶部

function goTopEx() {
    var obj = document.getElementById("goTopBtn");
    function getScrollTop() {
        return document.documentElement.scrollTop;
    }
    function setScrollTop(value) {
        document.documentElement.scrollTop = value;
    }
    window.onscroll = function () { getScrollTop() > 0 ? obj.style.display = "" : obj.style.display = "none"; }
    obj.onclick = function () {
        var goTop = setInterval(scrollMove, 10);
        function scrollMove() {
            setScrollTop(getScrollTop() / 1.1);
            if (getScrollTop() < 1) clearInterval(goTop);
        }
    }
}

4. Ajax

4.1. AJAX 简介

全称:Asynchronous Javascript and XML,由 Javascript+CSS+DOM+XMLHttpRequest+XSTL+XHTML+XML 七种技术组成,其中技术核心是 XMLHttpRequest。

4.2. 同步 vs 异步

同步:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。

4.3. XMLHttpRequest

var ajax = {
        get:function(url,func){
        // XMLHttpRequest 用于在后台与服务器交换数据
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.onreadystatechange = function() {
        // readyState == 4 说明请求已完成
        if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) {
                // 从服务器获得数据
              fn.call(this, xhr.responseText);
        }
    };
    xhr.send();
  },
  // data 应为 'a=a1&b=b1' 这种字符串格式,在 jquery 里如果 data 为对象会自动将对象转成这种字符串格式
  post: function (url, data, fn) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", url, true);
    // 添加 http 头,发送信息至服务器时内容编码类型
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
        fn.call(this, xhr.responseText);
      }
    };
    xhr.send(data);
  }
};

4.4. jQuery Ajax

4.4.1. Ajax 参数详解

$.ajax({
        url: URL, // 发送请求的地址(默认为当前页地址)
  type: "POST", // 请求方式:post/get/put/delete(默认为get)
  timeout: 600, // 请求超时时间,单位毫秒
  async:true, // true,异步请求;false,同步请求。
  cache:false, // true,从浏览器加载缓存;false,不从浏览器加载缓存
  data: JSON.stringify(stream), // 发送到服务器的数据,要求为Object或String类型的参数。
  dataType: "json",// 预期服务器返回的数据类型。可用的类型有:xml,html,script,json,jsonp,text
  contentType: "application/json; charset=utf-8", // 当发送信息至服务器时,内容编码类型。默认为"application/x-www-form-urlencoded",multipart/form-data:有时候也会这个,上传下载可能会用到。
  beforeSend: function(XMLHttpRequest){
        // 设置请求头,加载loading界面
  },
  dataFilter:function(){ //给Ajax返回的原始数据进行预处理的函数。提供data和type两个参数。data是Ajax返回的原始数据,type是调用jQuery.ajax时提供的dataType参数。
        //
  },
  global:false, //表示是否触发全局ajax事件。默认为true。
  ifModified:false, //仅在服务器数据改变时获取新数据。服务器数据改变判断的依据是Last-Modified头信息。默认值是false,即忽略头信息。
  jsonP:"",// 在一个jsonp请求中重写回调函数的名字。
  username:"zrg", //用于响应HTTP访问认证请求的用户名。
  password:"123456", //用于响应HTTP访问认证请求的密码。
  processData:false, // 默认情况下,发送的数据将被转换为对象(从技术角度来讲并非字符串)以配合默认内容类型"application/x-www-form-urlencoded"。如果要发送DOM树信息或者其他不希望转换的信息,请设置为false。
  scriptCharset:"", //只有当请求时dataType为"jsonp"或者"script",并且type是GET时才会用于强制修改字符集(charset)。通常在本地和远程的内容编码不同时使用。
  complete: function(XMLHttpRequest, textStatus){ // 请求完成后调用的回调函数(请求成功或失败时均调用)
        //
  },
  success: function (data,textStatus) { // 请求成功后调用的回调函数,有两个参数: (1)由服务器返回,并根据dataType参数进行处理后的数据;(2)描述状态的字符串。
        if (data.success) {
                //
      } else {
        //
      }
  },
  error: function(XMLHttpRequest, textStatus, errorThrown){ // 请求失败时被调用的函数。有3个参数,即XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。
        //
  }
});

4.4.2. 常见的 POST 提交数据方式

  1. application/x-www-form-urlencoded

    浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
    
  2. multipart/form-data

    一般用来上传文件
    
  3. application/json

    该方案可以方便的提交复杂的数据结构,特别适合 RESTful 的接口。
    
  4. text/xml

    XML 结构传输。
    XML-RPC(XML Remote Procedure Call),它是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。它的使用也很
    广泛,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服务等等。
    

4.4.3. 提交 Form 表单(包括文件上传)

4.4.3.1. 常规方法
$.ajax({
        url:"${pageContext.request.contextPath}/public/testupload",
    type:"post",
    data:{username:username},
    success:function(data){
        window.clearInterval(timer);
        //
    },
    error:function(e){
        //
    }
});

// 或者单一获取
var username = $("#username").val();
var password = $("#password").val();
...

// 以上方式,如果数量少的话,那还没有什么,但是如果数据十分大的话,那就十分的麻烦。

4.4.3.2. 使用 FormData 对象

// 下面就介绍提高开发效率的方法

// FormData对象是html5的一个对象,目前的一些主流的浏览器都已经兼容。
var form = new FormData();
form.append("username","zxj");
form.append("password",123456);
var req = new XMLHttpRequest();
req.open("post", "${pageContext.request.contextPath}/public/testupload", false);
req.send(form);
var form = new FormData();
form.append("username","zxj");
form.append("password",123456);
$.ajax({
        url:"${pageContext.request.contextPath}/public/testupload",
    type:"post",
    data:form,
    processData:false,
    contentType:false,
    success:function(data){
        window.clearInterval(timer);
            //
    }
});
4.4.3.3. 使用 jQuery.form.js
具体参考https://github.com/jquery-form/form

5. 地图

5.1. 坐标系转换

详细概述转到「PHP 开发笔记」查看

var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
var PI = 3.1415926535897932384626;
var a = 6378245.0;
var ee = 0.00669342162296594323;

var transformlat = function transformlat(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
  ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
  ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
  ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
  return ret
};

var transformlng = function transformlng(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
  ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
  ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
  ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
  return ret
};

/**
 * 判断是否在国内,不在国内则不做偏移
 * @param  {[type]} lng [description]
 * @param  {[type]} lat [description]
 * @return {[type]}     [description]
 */
 var out_of_china = function out_of_china(lng, lat) {
  var lat = +lat;
  var lng = +lng;
    // 纬度3.86~53.55,经度73.66~135.05
    return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
  };


/**
 * 百度地图BD09坐标->中国GCJ02坐标
 * 腾讯地图用的也是GCJ02坐标
 * @param  {[number]} bd_lon [经度]
 * @param  {[number]} bd_lat [纬度]
 * @return {[Array]}        [description]
 */
 var bd09togcj02 = function bd09togcj02(bd_lon, bd_lat) {
  var bd_lon = +bd_lon;
  var bd_lat = +bd_lat;
  var x = bd_lon - 0.0065;
  var y = bd_lat - 0.006;
  var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
  var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
  var gg_lng = z * Math.cos(theta);
  var gg_lat = z * Math.sin(theta);
  return [gg_lng, gg_lat];
};

console.log([102.730063, 25.074568]);
console.log(bd09togcj02(102.730063, 25.074568));
// 保留小数点后6位
// 102.723648, 25.068268

/**
 * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
 * 即谷歌、高德 转 百度
 * @param  {[number]} lng [经度]
 * @param  {[number]} lat [纬度]
 * @return {[Array]}        [description]
 */
 var gcj02tobd09 = function gcj02tobd09(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
  var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
  var bd_lng = z * Math.cos(theta) + 0.0065;
  var bd_lat = z * Math.sin(theta) + 0.006;
  return [bd_lng, bd_lat]
};

console.log(gcj02tobd09(102.723648, 25.068268));

/**
 * WGS84转GCj02
 * @param  {[type]} lng [description]
 * @param  {[type]} lat [description]
 * @return {[type]}     [description]
 */
 var wgs84togcj02 = function wgs84togcj02(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  if (out_of_china(lng, lat)) {
    return [lng, lat];
  } else {
    var dlat = transformlat(lng - 105.0, lat - 35.0);
    var dlng = transformlng(lng - 105.0, lat - 35.0);
    var radlat = lat / 180.0 * PI;
    var magic = Math.sin(radlat);
    magic = 1 - ee * magic * magic;
    var sqrtmagic = Math.sqrt(magic);
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
    dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
    var mglat = lat + dlat;
    var mglng = lng + dlng;
    return [mglng, mglat]
  }
};

console.log(wgs84togcj02(116.404, 39.915));


/**
 * GCJ02 转换为 WGS84
 * @param  {[type]} lng [description]
 * @param  {[type]} lat [description]
 * @return {[type]}     [description]
 */
 var gcj02towgs84 = function gcj02towgs84(lng, lat) {
  var lat = +lat;
  var lng = +lng;
  if (out_of_china(lng, lat)) {
    return [lng, lat];
  } else {
    var dlat = transformlat(lng - 105.0, lat - 35.0);
    var dlng = transformlng(lng - 105.0, lat - 35.0);
    var radlat = lat / 180.0 * PI;
    var magic = Math.sin(radlat);
    magic = 1 - ee * magic * magic;
    var sqrtmagic = Math.sqrt(magic);
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
    dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
    var mglat = lat + dlat;
    var mglng = lng + dlng;
    return [lng * 2 - mglng, lat * 2 - mglat]
  }
};

console.log(gcj02towgs84(116.404, 39.915));

6. 注意事项

6.0.1. JavaScript没有块级作用域

在其他类C的语言中,由 {} 封闭的代码块都有自己的作用域(如果用ECMAScript的话来讲,就是它们自己的执行环境)。

if(true){
    var color="blue";
}
alert(color); //"blue"

内容源于:《JavaScript高级程序设计》第3版 [美] Nicholas C.Zakas,p76.