关于正则表达式无法匹配手机号的问题

前提

今天要做输入框验证手机号和电话号码的功能,需要用到正则表达式,于是就在网上搜了这么一段正则验证的代码,也不知道能不能用,先试试再说:

^((0\d{2,3}-?\d{7,8})|(1[35784]\d{9}))$;

按道理来说,直接复制粘贴过去就可以使用了。但是,问题出现了:居然验证失败了。

我是这么使用的:(第一种方式)

<input type="text" id="phone">
<script>
    var phone = document.getElementById("phone");
    var number = phone.value;

    phone.onblur = function(){
        var pattern = new RegExp("^((0\d{2,3}-?\d{7,8})|(1[35784]\d{9}))$");//关键代码
        var result = pattern.test(number);
        if(number && !result){
            alert('格式错误!');
        }else{
            alert('格式正确!');
        }
    }
script>

方法一测试效果图

关于正则表达式无法匹配手机号的问题_第1张图片

分析

  • 心想:怎么可能,别人提供的代码按道理来说可以用的呀,怎么到我这里就没办法用,真奇怪。
  • 难道是这代码有问题?感觉不可能啊,我使用方法不对吗?
  • 于是,又找了几种正则验证的代码,测试后依然不能用。无论怎么试,提示结果都是一样——“格式错误!”
  • 此时,怀疑自己定义正则的方式不对。然后,查了一下定义正则表达式的语法。

知识点 —— 如何定义正则表达式

正则表达式的定义共有2种方式:

  • 显式定义:显式定义必须是使用new关键词来定义。

语法:

var 变量名 =  new RegExp("正则表达式模式");
  • 隐式定义:隐式定义的正则表达式开头和结尾都必须是斜杠“/”

语法:

var 变量名 =  /正则表达式模式/

注:
(1) 使用隐式定义的正则表达式是不需要使用双引号括起来的这一点跟显式定义的正则表达式不一样!
(2)隐式定义是最常用的方式建议大家以后都使用这种方式定义正则表达式,代码量少并且方便。

  • 大概看了一下定义语法,并没有发现任何异常,写的代码也没问题啊,奇了怪了。于是,就打算另辟蹊径,重新换一种实现的方式。

  • 因为之前在代码中见过有人使用data-属性的做法进行正则验证。而且重要的是这种做法我之前尝试过,可以成功的进行正则验证。

  • 做法:将正则验证的代码放在的HTML标签的data-属性中保存起来,等需要用的时候,直接用js获取标签的属性值就可以了。随后使用test()方法进行相关的验证。

  • 其实性质都是一样的,只是换了一种实现方式而已。废话不多说,直接上代码。

第二种方式代码实现如下:

<input type="text" id="phone" data-pattern="^((0\d{2,3}-?\d{7,8})|(1[35784]\d{9}))$">
<script>
    var phone = document.getElementById("phone");
    var number = phone.value;

    phone.onblur = function(){
        //写完后,感觉这两种方法并没有什么差别啊,就是猫叫了个咪而已。
        //只是正则验证代码写的地方不同罢了。一个是直接定义的,一个是写在了data属性中。
        var pattern = new RegExp(phone.getAttribute("data-pattern"));//关键代码
        var result = pattern.test(number);
        if(number && !result){
            alert('格式错误!');
        }else{
            alert('格式正确!');
        }
    }
script>

果不其然,这种方式奏效了,成功的弹出了“格式正确!”的提示框。

方法二测试效果图

关于正则表达式无法匹配手机号的问题_第2张图片

为什么直接定义的正则表达式就验证失败了。而间接定义的方式居然可以验证成功。不科学啊!这令我百思不得其解。

事已至此,只有破釜沉舟,作最后一搏。我就不信找不到问题所在。心想:在控制台打断点调试一下不就行了。

做法:
将代码的每一步都打上断点,逐步调试看输出结果。然后将两种方法的调试内容进行对比,看有没有什么差异。

方法二的断点调试图

关于正则表达式无法匹配手机号的问题_第3张图片

方法一的断点调试图

关于正则表达式无法匹配手机号的问题_第4张图片

通过一番调试,终于被细心的我发现了极其细微的差别

关于正则表达式无法匹配手机号的问题_第5张图片

区别如下:

  • 使用正则表达式的构造函数RegExp()定义的正则表达式对象,所生成的匹配模式中,居然将元字符\d识别成了字母d反斜杠\这个字符呢,怎么没了?
  • 而将正则表达式的定义作为字符串设置在标签的data-属性中,居然可以正确识别出来,不会出错。

疑问:这到底是为什么呢?

想着想着,突然灵光一闪,有答案了,我想我应该知道是怎么回事了。

答案:肯定是反斜杠\的原因。

  • 因为反斜杠\js中是作为转义字符\而存在的,这个字符具有特定的语法含义,不能被当做普通的字符来解析的。
  • 如果要使用普通意义下的反斜杠,必须用转义字符进行转义才行,否则在语法上是行不通的。
  • 就像这样:\\ 转义一下就可以了。

其实,说到底都怪自己太粗心了。在看如何定义正则表达式语法时,过于寻求答案,而忽略了原文中重要的知识点说明,这才导致自己一路错下来。

说明:显式定义的正则表达式必须要使用双引号括起来,这里要注意字符串的转义。
【本来是极其重要的一句话,结果我没注意到,还好及时发现了】

改进后的代码

var pattern = new RegExp("^((0\\d{2,3}-?\\d{7,8})|(1[35784]\\d{9}))$");//注意字符串的转义

改进后的调试效果图

这里写图片描述

最后,顺便测试了一下隐式定义正则表达式的方法。这种方式定义的正则表达式,字符串不需要进行转义。

var pattern = /^((0\d{2,3}-?\d{7,8})|(1[35784]\d{9}))$/;

隐式定义的调试效果图

这里写图片描述

结束语

关于正则表达式的语法,心里一定要非常清晰明了,不是百度到答案后直接粘贴复制就能使用的。在使用之前还得根据情况来判断是否适用。

关于正则表达式的定义我们必须要知道的:

  • 显式定义必须是使用new关键词来定义。
  • 显式定义的正则表达式必须要使用双引号括起来这里要注意字符串的转义
  • 隐式定义的正则表达式开头和结尾都必须是斜杠“/”
  • 使用隐式定义的正则表达式是不需要使用双引号括起来的。(这一点要区别于显式定义的正则表达式)
  • 隐式定义是最常用的方式,建议大家以后都使用隐式定义的方式定义正则表达式,代码量少并且方便。

你可能感兴趣的:(JavaScript,基础教程)