首页 文章 精选 留言 我的

精选列表

搜索[JavaScript],共9119篇文章
优秀的个人博客,低调大师

身份证号码的正则表达式及验证详解(JavaScript,Regex)

简言 在做用户实名验证时,常会用到身份证号码的正则表达式及校验方案。本文列举了两种验证方案,大家可以根据自己的项目实际情况,选择适合的方案。 身份证号码说明 居民身份证号码,正确、正式的称谓应该是“公民身份号码”。根据【中华人民共和国国家标准 GB 11643-1999】中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 以北京市朝阳区一女性身份证号码为例,身份证号码所表示的含义如下图所示: 注:该身份证号码来源于国标【GB 11643-1999】。 下面我们就从零开始完成一个完整的身份证号码校验过程。 方案1 (简单) 1.1 分部规则 我们首先提出方案1,并分步做如下规则定义: 1.1.1 地址码规则: 地址码长6位 以数字1-9开头 后5位为0-9的数字 根据以上规则,写出地址码的正则表达式: /^[1-9]\d{5}/ 1.1.2 年份码规则: 年份码长4位 以数字18,19或20开头 剩余两位为0-9的数字 根据以上规则,写出年份码的正则表达式: /(18|19|20)\d{2}/。如果不需要18开头的年份,可以去掉18。 1.1.3 月份码规则: 月份码长2位 第一位数字为0,第二位数字为1-9 或者第一位数字为1,第二位数字为0-2 根据以上规则,写出月份码的正则表达式: /((0[1-9])|(1[0-2]))/。 1.1.4 日期码规则: 日期码长2位 第一位数字为0-2,第二位数字为1-9 或者是10,20,30,31 根据以上规则,写出日期码的正则表达式 :/(([0-2][1-9])|10|20|30|31)/。 1.1.5 顺序码规则: 顺序码长3位 顺序码是数字 根据以上规则,写出顺序码的正则表达式 :/\d{3}/。 1.1.6 校验码规则: 校验码长1位 可以是数字,字母x或字母X 根据以上规则,写出校验码的正则表达式 :/[0-9Xx]/。 1.2 方案1正则表达式 综合以上6条规则,给出完整的正则表达式及测试程序如下: var p = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; //输出 true console.log(p.test("11010519491231002X")); //输出 false 不能以0开头 console.log(p.test("01010519491231002X")); //输出 false 年份不能以17开头 console.log(p.test("11010517491231002X")); //输出 false 月份不能为13 console.log(p.test("11010519491331002X")); //输出 false 日期不能为32 console.log(p.test("11010519491232002X")); //输出 false 不能以a结尾 console.log(p.test("11010519491232002a")); 演示代码 1.3 方案1分析 方案1只是做了基本的格式判定,存在三个主要的不足: 地址码判定不够精确。例:我国并不存在16,26开头的地区,却可通过验证 日期判定不够精确。例:19490231也可通过验证,而2月并不存在31日 校验码是由17位本体码计算得出,方案1并未校验此码 方案2 (全面) 根据方案1的不足,引入方案2进而改进方案1的不足。 2.1 省级地址码校验 华北:北京11,天津12,河北13,山西14,内蒙古15 东北: 辽宁21,吉林22,黑龙江23 华东: 上海31,江苏32,浙江33,安徽34,福建35,江西36,山东37 华中: 河南41,湖北42,湖南43 华南: 广东44,广西45,海南46 西南: 四川51,贵州52,云南53,西藏54,重庆50 西北: 陕西61,甘肃62,青海63,宁夏64,新疆65 特别:台湾71,香港81,澳门82 根据上述地址码做身份证号码的前两位校验,进一步的提高准确率。当前的地址码以2013版的行政区划代码【GB/T2260】为标准。由于区划代码的历史演变,使得地址码后四位校验变得不太可能。以三胖的身份证号为例,本人号码是2321开头,而当前行政区划代码表中并无此代码。因此本文只做前两位省级地址码的校验。 也有说法表述91开头是外国人取得中国身份证号码的前两位编码,但本人并未得到证实。如有持91开头身份证或认识马布里的,请帮忙确认相关信息。 根据以上分析,给出省级地址码校验及测试程序如下: var checkProv = function (val) { var pattern = /^[1-9][0-9]/; var provs = {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:"澳门"}; if(pattern.test(val)) { if(provs[val]) { return true; } } return false; } //输出 true,37是山东 console.log(checkProv(37)); //输出 false,16不存在 console.log(checkProv(16)); 演示代码 2.2 出生日期码校验 出生日期码的校验不做解释,直接给出如下函数及测试程序: var checkDate = function (val) { var pattern = /^(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)$/; if(pattern.test(val)) { var year = val.substring(0, 4); var month = val.substring(4, 6); var date = val.substring(6, 8); var date2 = new Date(year+"-"+month+"-"+date); if(date2 && date2.getMonth() == (parseInt(month) - 1)) { return true; } } return false; } //输出 true console.log(checkDate("20180212")); //输出 false 2月没有31日 console.log(checkDate("20180231")); 演示代码 2.3 校验码校验 校验码的计算略复杂,先给出如下公式: 其中 ai 表示身份证本体码的第 i 位值,而 Wi 表示第 i 位的加权因子值。 加权因子表 【表1】: i 1 2 3 4 5 6 7 8 Wi 7 9 10 5 8 4 2 1 9 10 11 12 13 14 15 16 17 6 3 7 9 10 5 8 4 2 X与校验码换算表 【表2】 X 0 1 2 3 4 5 6 7 8 9 10 a18 1 0 X 9 8 7 6 5 4 3 2 算法过程: 根据身份证主体码(前17位)分别与对应的加权因子(表1)计算乘积再求和,根据所得结果与11取模得到X值。 根据 X 值查询表2,得出a18即校验码值。 校验码计算程序及测试见如下代码: var checkCode = function (val) { var p = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; var factor = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ]; var parity = [ 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 ]; var code = val.substring(17); if(p.test(val)) { var sum = 0; for(var i=0;i<17;i++) { sum += val[i]*factor[i]; } if(parity[sum % 11] == code.toUpperCase()) { return true; } } return false; } // 输出 true, 校验码相符 console.log(checkCode("11010519491231002X")); // 输出 false, 校验码不符 console.log(checkCode("110105194912310021")); 演示代码 2.4 方案2整体代码 var checkID = function (val) { if(checkCode(val)) { var date = val.substring(6,14); if(checkDate(date)) { if(checkProv(val.substring(0,2))) { return true; } } } return false; } //输出 true console.log(checkID("11010519491231002X")); //输出 false,校验码不符 console.log(checkID("110105194912310021")); //输出 false,日期码不符 console.log(checkID("110105194902310026")); //输出 false,地区码不符 console.log(checkID("160105194912310029")); 演示代码 以上为三胖对身份证号码验证的理解和分析,如有不足请大家予以指正。 知名物理学家史蒂芬?霍金于2018年3月14日去世,享年76岁。一个博学又有趣的人,一路走好! 世间再无霍金,时间永留简史! 原文地址

优秀的个人博客,低调大师

JavaScript 中 structuredClone 的深拷贝:为什么有时比 JSON.parse(JSON.stringify()) 更可靠

日常开发里经常需要把一个对象完整复制出来,避免修改副本时影响原数据。过去最常见写法是 JSON.parse(JSON.stringify(obj)),它简单、兼容性好,但遇到 Date、RegExp、Map、Set、ArrayBuffer、循环引用时会直接失效:日期变成字符串,正则变为空对象,Map 和 Set 直接变成 {},循环引用会抛出异常。浏览器和 Node.js 从较新版本开始提供了全局方法 structuredClone,它基于结构化克隆算法,能处理这些类型,还支持循环引用、File、Blob、ImageData 等。这篇文章不会罗列 API 文档,而是从真实业务场景出发,看它和 JSON 方案的差异、边界、错误处理,以及什么情况下仍然要手写递归或使用第三方库。

优秀的个人博客,低调大师

JavaScript 正则匹配中的 lastIndex 陷阱:为什么 test 和 exec 会交替返回 true 和 false

用同一个正则对象反复测试不同字符串,明明字符串都匹配,却出现一次 true 一次 false 的诡异现象,这是不少人在表单校验、循环过滤或批量替换时踩过的坑。问题大多不在正则模式本身,而是带了 g 或 y 标志的正则对象会维护 lastIndex 状态。调用 test 和 exec 时,匹配成功会更新这个值,下一次从新位置继续找,匹配失败才把它重置为 0。于是跨字符串复用同一实例时就容易出现交替结果。这篇文章从 JS 引擎的执行规则出发,解释 lastIndex 的行为边界,给出几种可靠的修正写法,并说明为什么在 React 组件、工具函数和模块级常量的场景里尤其容易撞上这个坑,以及如何通过代码审查和测试提前发现。

优秀的个人博客,低调大师

JavaScript 中 structuredClone 的实战坑:为什么你的深拷贝在 class 实例上翻车了?

在维护一个后台管理系统时,我需要把一份包含日期、Map 和自定义 class 实例的配置对象深拷贝到草稿状态里。以前一直用 JSON.parse(JSON.stringify(obj)),但它会把 Date 变成字符串、丢掉 undefined,更麻烦的是遇到 class 实例直接变成普通对象,方法全没了。后来我换成了浏览器原生的 structuredClone,大部分场景确实好使,但有一次拷贝一个带 getter 的 class 实例时,拷贝出来的对象属性直接变成 undefined,排查了半天才发现 structuredClone 虽然能处理循环引用和内置类型,但它不会保留原型链。这篇文章从实际代码出发,讲清楚 structuredClone 和 JSON 深拷贝的边界在哪、哪些数据结构它会静默丢信息、以及怎么用 MessageChannel 或手写递归补上原型和 getter 的坑,顺便对比 lodash.cloneDeep 在 class 场景下的表现。

优秀的个人博客,低调大师

JavaScript 里 Promise 链中 then 回调抛错后,后面的 catch 为什么有时接不住?

写业务代码时经常遇到这种状况:一个接口请求失败后,你在 .then() 里做了错误处理,但代码还是走到了全局的 unhandledrejection 事件,控制台飘红。或者反过来,明明某个 .then() 里 throw new Error() 了,后面的 .catch() 却像没看见一样,最后错误跑到了另一个分支里。这不是 Promise 实现有 bug,而是很多人对 then 链的返回值传递和错误冒泡机制理解得不够完整。Promise 的错误处理依赖链式调用中每个环节的返回状态,一旦在某个 then 里把 rejection 消化掉,或者返回了一个新的 Promise 把错误吞了,后续的 catch 就永远接不到。这篇文章会从几个真实的代码片段出发,梳理 then 链里错误是怎么一级一级往下传的,以及为什么有时 catch 写了却没生效。

优秀的个人博客,低调大师

网页里的 JavaScript 能不能监听浏览器窗口外的键盘和鼠标事件

我在网页里给 document 注册一个 keydown,再给 window 注册一个 mousedown,页面内操作时一切正常。鼠标一旦点到 Windows 任务栏、地址栏、另一个浏览器窗口,或者切换到 VS Code,监听器立刻安静下来。很多前端开发者遇到这里,会继续尝试把监听器挂到 window,把事件阶段改成捕获阶段,再把 React 的事件写法换成原生 DOM 写法。结果并不会改变。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册