1. 验证正则表达式中的全局g对几种方法的影响
- test校验方法:正则的方法
- 总结:1)不添加全局g时,lastIndex值始终是0,所以每次检验匹配时,都是从0开始查找,查找到就返回true,查找不到就返回false;2)添加全局g后,test方法会对lastIndex值进行叠加改变,每检验一次,lastIndex值就改变一次,下次查找的时候从lastIndex值开始查找;
<script> var str="yuanmeng00huadianyuanmenghuadian11"; var reg=/yuanmeng\d+/; var reg1=/yuanmeng\d+/g; //不添加全局g; console.log(reg.test(str));//结果为true; //添加全局g; console.log(reg1.lastIndex);//结果为0; console.log(reg1.test(str));//结果为true;查找到的结果为yuanmeng00; console.log(reg1.lastIndex);//结果为10; console.log(reg1.test(str));//结果为false,从索引为10的字符开始查找,查找不到,返回null; </script>
- exec方法:正则的方法
- 总结:1)不添加全局g,每次查找的时候,都是从0开始,reg的lastIndex一直是0;2)正则exec方法中添加g,那么,每使用一次就查找一个,然后以数组的形式输出,每次查找输出后,下次查找的位置通过reg的lastIndex属性值记录住,再次使用exec方法查找时,就从上次结束的地方开始查找;
<script> var str="yuanmenghuadianyuanmenghuadian11"; var reg=/yuanmeng/; var reg1=/yuanmeng/g; //2.1 验证不添加全局g console.log(reg.exec(str));//结果为:["yuanmeng", index: 0, input: "yuanmenghuadianyuanmenghuadian11", groups: undefined] console.log(reg.lastIndex);//结果为:0 console.log(reg.exec(str));//结果为:["yuanmeng", index: 0, input: "yuanmenghuadianyuanmenghuadian11", groups: undefined] console.log(reg.lastIndex);//结果为:0 console.log(reg.exec(str));//结果为:["yuanmeng", index: 0, input: "yuanmenghuadianyuanmenghuadian11", groups: undefined] console.log(reg.lastIndex);//结果为:0 //总结:不添加全局g,每次查找的时候,都是从0开始,reg的lastIndex一直是0; //2.2 验证添加全局g console.log(reg1.exec(str));//结果为:["yuanmeng", index: 0, input: "yuanmenghuadianyuanmenghuadian11", groups: undefined] console.log(reg1.lastIndex);//结果为:8 console.log(reg1.exec(str));//结果为:["yuanmeng", index: 15, input: "yuanmenghuadianyuanmenghuadian11", groups: undefined] console.log(reg1.lastIndex);//结果为:23 console.log(reg1.exec(str));//结果为:null console.log(reg1.lastIndex);//结果为:0 console.log(reg1.exec(str));//结果为:["yuanmeng", index: 0, input: "yuanmenghuadianyuanmenghuadian11", groups: undefined] //总结:正则exec方法中添加g,那么,每使用一次就查找一个,然后以数组的形式输出,每次查找输出后,下次查找的位置通过reg的lastIndex属性值记录住,再次使用exec方法查找时,就从上次结束的地方开始查找; </script>
- match方法:字符串的方法
- 总结:字符串match方法,本质就是查找内容,查找到一个就返回一个数组,数组中有三项;与exec方法获取的相同;
- 总结:1)当不添加全局g时;match方法相当于exec方法,查找到内容,以一个数组的方式返回,里面有三项;2)当添加全局g时,match方法,就把所有满足reg规则的内容,作为数组元素,返回一个新的数组;
<script> var str="yuanmenghuadianyuanmenghuadian11"; var reg=/yuanmeng/; var reg1=/yuanmeng/g; console.log(str.match(reg));//结果为:["yuanmeng", index: 0, input: "yuanmenghuadianyuanmenghuadian11", groups: undefined] console.log(str.match(reg1));//结果为:["yuanmeng", "yuanmeng"] //总结:当不添加全局g时;match方法相当于exec方法,查找到内容,以一个数组的方式返回,里面有三项; //当添加全局g时,match方法,就把所有满足reg规则的内容,作为数组元素,返回一个新的数组; </script>
- replace方法:字符串的方法
- 总结:1)字符串replace方法在使用的时候,只要在字符串中只要找到一个被替换的内容,就停止,然后替换掉,返回一个新的字符串;注意:只要找到一个就结束;2)当正则的表达式不添加全局g时,此时就代表查找一次,当使用的时候,只要找到一个,也是停止,只不过是把替换的内容,换成了一个规则,本质没有变化;3)当正则表达式中添加了全局g后,意思是在全局中查找,是查找所有满足正则规则的内容,然后进行全部替换,返回新的字符串;
<script> var str="yuanmenghuadianyuanmenghuadian11"; var reg=/yuanmeng/; var reg1=/yuanmeng/g; console.log(str.replace(reg,"meihao"));//结果为:meihaohuadianyuanmenghuadian11 console.log(str.replace(reg1,"meihao"));//结果为:meihaohuadianmeihaohuadian11 //总结,不添加全局g,那么在查找的时候,找到一个就停止,然后替换掉,再结束,返回新的字符串; //添加全局g,那么在查找的时候,查找到全部,然后全部替换,再结束,返回新的字符串; </script>
2. 字符串的repalce方法与正则配合后的变化
- 总结:
- 字符串replace方法,本质就是查找被替换的内容,然后将其替换,返回一个新的字符串,但是需注意的一点是,每次查找只查找一个,只要有一个就停止,然后替换一个,结束,不会同时替换两个满足要求的内容;
- 不添加全局g,跟上述方法结果一样,仍然只是查找一个,然后替换一个,结束;
- 添加全局g,改变查找规则,在查找的时候,将满足规则的内容全部查找到,然后全部替换,最后结束;
- 正则改变的,只是一个规则,不会改变replace的特性,只是改变了查找规则;
- 实质:字符串原有的replace方法,特性没有改变,只不过是通过添加正则,来改变了查找的规则;由原来的查找一个,改为查找所有,而这个起决定性作用的就是正则,它制定的规则;
<script>
//需求:利用字符串的replace方法,将str中的两个huadian,全都替换成huandianxiehe;
var str="huadianhuadian";
str=str.replace("huadian","huadianxiehe");
console.log(str);//结果为:huadianxiehe huadian;
str=str.replace("huadian","huadianxiehe");
console.log(str);//结果为:huadianxiehe xiehe huadian;
//总结:字符串replace方法,本质就是查找被替换的内容,然后将其替换,返回一个新的字符串,但是需注意的一点是,每次查找只查找一个,只要有一个就停止,然后替换一个,结束,不会同时替换两个满足要求的内容;
//替换一次,然后再添加代码,去替换第二次的时候,是从第一个开始查找,如果中途查找到内容,就会停止,不会再继续,导致的问题是,最后那个huadian永远不会被查找到;
//正则中的replace方法;
//1.正则表达式中不添加全局g;
var str="huadianhuadian";
var reg=/huadian/;
str=str.replace(reg,"huadianxiehe");
console.log(str);//结果为:huadianxiehe huadian
str=str.replace(reg,"huadianxiehe");
console.log(str);//结果为:huadianxiehe xiehe huadian
//总结:不添加全局g,跟上述方法结果一样,仍然指挥查找一个,然后替换一个,结束;
//2. 正则中添加全局g,
var str="huadianhuadian";
var reg=/huadian/g;
console.log(str.replace(reg,"huadianxiehe"));//结果为:huadianxiehe huadianxiehe
//总结,添加全局g,改变查找规则,在查找的时候,将满足规则的内容全部查找到,然后全部替换,最后结束;
//大总结:正则改变的,只是一个规则,不会改变replace的特性,只是改变了查找规则;
//实质:字符串原有的replace方法,特性没有改变,只不过是通过添加正则,来改变了查找的规则;由原来的查找一个,改为查找所有,而这个起决定性作用的就是正则,它制定的规则;
</script>
3. replace方法中的回调函数
- 回调函数:把函数的定义阶段作为参数,赋给另外一个函数,这样的函数就叫做回调函数;
- replace方法中的回调函数:
- replace方法中的回调函数调用的次数,取决于正则匹配的次数,匹配几次,就调用几次;
- replace方法,每查找到一次符合正则的内容,就调用一次函数,同时传入当前获取内容的三项参数,其实可看作对内容的所有满足情况的遍历;
- replace方法中的回调函数会传入实参,传入的内容为exec获得的三项内容值,如1)item:大正则内容(如果有小分组,则第二项为小分组的内容);2)index:每次查找到的内容,开头对应的索引值;3)input:字符串;
<script> //回调函数:把函数的定义阶段作为一个参数赋给另外一个函数,这个函数就叫做回调函数; var str="yuanmengyuanmeng"; var reg=/yuanmeng/g; //replace中的回调函数调用的次数,取决于正则匹配成功的次数; //replace中的回调函数,拿到的参数跟exec拿到的返回值是一样的; str=str.replace(reg,function (item,index,input) { //检验回调函数中传入了哪些实参,用arguments console.log(arguments);//结果为:["yuanmeng", 0, "yuanmengyuanmeng"]; return "yuanmengpeixun"; }); console.log(str);//结果为:yuanmengpeixunyuanmengpeixun </script>
- 实例1:过滤敏感词,即利用replace方法,将特定的词替换成对应数目的*号;
- 知识点:replace方法中使用回调函数,获取第一个大正则内容参数;
<body> <textarea id="t1" cols="30" rows="10"> 天空蓝和美丽的大地收到印度那地方黑发黑非法是否IE或打开IE减肥,印度减肥而恢复饿得慌IE反对党的凤飞飞欢迎和热爱,祖国人民都非常爱戴天空蓝和美丽的大地; </textarea> <input type="button" value="过滤敏感词"/> <textarea id="t2" cols="30" rows="10"></textarea> <script> var oT1=document.getElementById("t1"); var oT2=document.getElementById("t2"); var oBtn=document.getElementsByTagName("input")[0]; var reg=/(天空蓝|美丽的大地|印度)/g; oBtn.onclick=function(){ oT2.value=oT1.value.replace(reg,function (item) { //此时获得的第一个参数为大正则内容,如天空蓝,美丽的大地,印度,这些都是字符串,遍历字符串,来决定*的个数 var str=""; for(var i=0; i<item.length; i++){ str+="*"; } return str; }); }; </script> </body>
- 实例2:模板修改
- 知识点:replace方法中使用回调函数,回调函数中传入的第一项为大正则的内容,第二项为小分组的内容;
<script> var str="my name is {0},i come from {1},my age is {2}"; var ary=["果木山","保定",26]; var reg=/{(\d)}/g; var res=str.replace(reg,function ($1, $2) { //$1代表大正则的内容,$2代表小分组的内容 return ary[$2]; }); console.log(res);//结果为:"my name is 果木山,i come from 保定,my age is 26" </script>
- 实例3:数字变汉字
<script> //需求:将数字变为汉字; var str="我以后的目标是工资达到15555元"; var ary=["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"]; var res=str.replace(/\d/g,function ($1) { return ary[$1]; }); console.log(res);//结果为:我以后的目标是工资达到壹伍伍伍伍元 </script>
- 实例4:去除字符串中的空格
<script> var str=" meihoa miehfaofie "; //需求1:只去除开头和结尾的空格 var reg=/(^\s+)|(\s+$)/g; var res=str.replace(reg,""); console.log("("+res+")");//结果为:(meihoa miehfaofie) //需求2:去除所有的空格 var reg2=/\s+/g; var res2=str.replace(reg2,""); console.log("("+res2+")")//结果为:(meihoamiehfaofie) </script>
- 实例5:利用对象不重名的特性来统计字母的重复次数
- 思路:
- 利用对象的不重名特性,统计单词,以及出现的次数
- 找到出现最多的次数;假设法
- 通过次数找字母
<script> //需求:求出现次数最多的单词(不分大小写),以及出现了多少次; //第一步:利用对象的不重名特性,统计单词,以及出现的次数 var str="aaaabbdddDJJJLLLIIEEaaBBDbbcccCCC"; var obj={}; for(var i=0; i<str.length; i++){ var cur=str[i].toLowerCase(); if(obj[cur]){ obj[cur]++; }else{ obj[cur]=1; } } //第二步:找到出现最多的次数; //假设法:假设a的次数最多 var max=obj.a; for(var attr in obj){ if(obj[attr]>max){ max=obj[attr]; } } //第三步,通过次数找单词 var ary=[]; for(var atr in obj){ if(obj[atr]==max){ ary.push(atr); } } var str=ary.join("、"); console.log("出现最多次数的单词是:"+str);//结果为:出现最多次数的单词是:a、b、c console.log("出现的最多的次数是"+max+"次");//结果为:出现的最多的次数是6次 </script>
- 思路:
4. replace方法与exec方法及match方法之间的联系
- exec方法:目的是捕获满足reg规则的内容,返回一个数组,数组中有三项;每次只能拿到一个满足规则的内容;
- match方法:目的是查找所有满足reg规则的内容,然后组成一个新的数组,返回;可以拿到全部满足规则的内容;
- replace方法:目的也是查找所有满足reg规则的内容,进行替换;但是当存在回调函数时;其目的跟match方法很像;每查找到一次,回调函数就执行一次,就传入一次参数,参数值与exec获得的值相同,意思就是对exec进行了多次使用,直到查找完;同时在回调函数中获取的第一项,就是每次查找到的内容,每调用一次回调函数,就是获取match方法获得的数组中的每一项,也就是对match方法获取数组进行一次遍历;
5.RegExp类实例私有属性lastIndex
- lastIndex属性:正则RegExp类实例的私有属性;
- 正则表达式中,若不添加全局g,则lastIndex值始终为0,test方法和exec方法不会改变它,每次查找都从0开始查找;
- 正则表达式中,若添加全局g;则test方法和exec方法,都会对lastIndex值产生影响,lastIndex值记录本次查找到内容后,内容结尾的下一项的索引值,下次再查找时,会继续从lastIndex值开始查找;两种方法混合使用时,会对lastIndex值进行叠加影响;
<script> var str="meihao1231meihao443343tiankong23243meihao5"; var reg=/meihao\d{1}/; //1.当不填加全局g时,lastIndex值一直为0; console.log(reg.lastIndex);//结果为:0; console.log(reg.exec(str));//结果为:["meihao1", index: 0, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined] console.log(reg.lastIndex);//结果为:0; console.log(reg.exec(str));//结果为:["meihao1", index: 0, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined] console.log(reg.lastIndex);//结果为:0; console.log(reg.exec(str));//结果为:["meihao1", index: 0, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined] //2.当添加了全局g后,lastIndex值会变化 //2.1 exec对lastIndex的影响 var reg1=/meihao\d{1}/g; console.log(reg1.lastIndex);//结果为:0; console.log(reg1.exec(str));//结果为:["meihao1", index: 0, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined] console.log(reg1.lastIndex);//结果为:7; console.log(reg1.exec(str));//结果为:["meihao4", index: 10, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined] console.log(reg1.lastIndex);//结果为:17; console.log(reg1.exec(str));//结果为:["meihao5", index: 35, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined] console.log(reg1.lastIndex);//结果为:42; console.log(reg1.exec(str));//结果为:null; console.log(reg1.lastIndex);//结果为:0; console.log(reg1.exec(str));//结果为:["meihao1", index: 0, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined] //总结:exec方法会对lastIndex值进行影响;lastIndex值记录本次查找到内容后,内容结尾的下一项的索引值,下次再查找时,会继续从lastIndex值开始查找; //2.2 test对lastIndex的影响 var reg2=/meihao\d{1}/g; console.log(reg2.lastIndex);//结果为:0; console.log(reg2.test(str));//结果为:true; console.log(reg2.lastIndex);//结果为:7; console.log(reg2.test(str));//结果为:true; console.log(reg2.lastIndex);//结果为:17; console.log(reg2.test(str));//结果为:true; console.log(reg2.lastIndex);//结果为:42;此时开始查找的位置是最后一位的下一位;后面已经没有东西,所以查找不到对应内容; console.log(reg2.test(str));//结果为:false; console.log(reg2.lastIndex);//结果为:0;重新从开始查找,循环; console.log(reg2.test(str));//结果为:true; //总结:test方法会对lastIndex值进行影响;lastIndex值记录本次查找到内容后,内容结尾的下一项的索引值,下次再查找时,会继续从lastIndex值开始查找; //2.3 两种方法混合使用对lastIndex值的影响; var reg3=/meihao\d{1}/g; console.log(reg3.lastIndex);//结果为:0; console.log(reg3.test(str));//结果为:true; console.log(reg3.lastIndex);//结果为:7; console.log(reg3.exec(str));//结果为:["meihao4", index: 10, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined]; console.log(reg3.lastIndex);//结果为:17; console.log(reg3.test(str));//结果为:true; console.log(reg3.lastIndex);//结果为:42; console.log(reg3.exec(str));//结果为:null; console.log(reg3.lastIndex);//结果为:0; console.log(reg3.exec(str));//结果为:["meihao1", index: 0, input: "meihao1231meihao443343tiankong23243meihao5", groups: undefined]; //总结:两种方法混用时,会对正则上面的属性lastIndex值进行重复修改;每次校验或exec捕获时,都是从lastIndex值开始; </script>
- 实例:
<script> var str="alpha(opacity:10)"; var reg=/alpha\(opacity:(\d+)\)/g;//小括号当做字符使用时,需要加转义符; console.log(reg.lastIndex);//结果为0; if(reg.test(str)){//此时使用test方法,将lastIndex值改变 console.log(reg.lastIndex);//结果为17;下次操作时,从索引17开始查找; console.log(reg.exec(str));//结果为null;此时exec将lastIndex值再次改变; console.log(reg.lastIndex);//结果为0; }else{ alert(false); } //正则中添加全局g后,每次进行test检验或exec捕获后,都会对lastIndex值进行改变; </script>
6.RegExp类静态属性
- RegExp类静态属性:类作为对象角色,添加的属性,成为对象的私有属性,与实例无关,但是必须在进行test方法或exec方法匹配后,才可以使用$1来获取小分组内容;
<script> var str="alpha(opacity:10)"; var reg=/alpha\(opacity:(\d+)\)/;//小括号当做字符使用时,需要加转义符; console.log(RegExp.$1);//结果为:空;意思是默认情况下RegExp类对象上不存在$1属性,必须匹配后,才具有; if(reg.test(str)){ console.log(RegExp.$1);//结果为:10; }else{ alert(false); } //exec方法和test方法,是正则类原型身上的公有属性; //私有属性必须配合exec方法和test方法使用,指的就是匹配到小分组,才能获取私有属性; //$1是正则类作为对象时,身上的私有属性,也成为静态属性; //其中$1,第一个小分组内容;$2,第二个小分组内容 //不会改变lastIndex属性; </script>
7. 重复子项
- 定义:重复子项,就是如"\1","\2"等字符,代表的意思是:"\1"指与第一个小分组的样式一样;"\2"指与第二个小分组的样式一样;
<script> //重复子项:就是\1跟第一个小分组一样;\2跟第二个小分组一样; var reg=/\w(\w)\1(\w)\2/; console.log(reg.test("abbcc"));//结果为:true; console.log(reg.test("12233"));//结果为:true; //正则reg的意思是,总共五位数,第三位与第二位相同(第一个小分组),第五位和第四位相同(第二个小分组); var reg2=/\w(\w)(\w)\w\1\2/; console.log(reg2.test("abcdbc"));//结果为:true; console.log(reg2.test("abcdbb"));//结果为:false; //正则reg2的意思是,总共六位数,第五位与第二位相同(第一个小分组),第六位与第三位相同(第二个小分组); //重复子项\1,\2的位置不重要,它们代表的是跟小分组一样的东西; </script>
- 实例:利用重复子项来统计字母的重复次数
- 思路:
- 将str进行排序,按照拼音形式,让重复的字母挨在一起;
- 书写正则样式,使用replace方法
- 知识点:
- 字符串转数组方法,数组sort方法,数组转回字符串方法;
- 正则表达式
var reg=/(\w)\1+/gi
分析:第一位为字母数字下划线,第二位跟第一位相同,"+"代表可以有多个重复的,"g"代表全局搜索多项,"i"代表忽略大小写; - replace方法中回调函数的参数
<script> var str="aaaabbdddDJJJLLLIIEEaaBBDbbcccCCC"; //第一步:将str进行排序,按照拼音形式 //分析:字符串转数组,数组sort方法,数组转回字符串 var ary=str.split("");//分离器为空的字符串; ary.sort(function (a, b) { return a.localeCompare(b); });//sort方法,按照拼音a-z的顺序排列; var str2=ary.join("");//连接符为空的字符串; // 此时str2为"aaaaaabbbbBBcccCCCdddDDEEIIJJJLLL"; //第二步:书写正则样式,使用replace方法 var reg=/(\w)\1+/gi; //分析:第一位为字母数字下划线,第二位跟第一位相同,"+"代表可以有多个重复的,"g"代表全局搜索多项,"i"代表忽略大小写; var max=0; var maxStr=""; str2.replace(reg,function ($1,$2) { //此时,获得的参数,第一项为大正则的内容,第二项为小分组的内容; //$1的长度用于获取重复字母的次数,$2用于获取重复的字母 //假设法,判断最大值; if($1.length>max){ max=$1.length; maxStr=$2; }else if($1.length==max){ maxStr+="和"+$2; } }); console.log("出现的最多的次数是"+max+"次");//结果为:出现的最多的次数是6次 console.log("出现最多次数的单词是:"+maxStr);//结果为:出现最多次数的单词是:a和b和c </script>
- 思路:
8. 封装urlParse()方法
- 需求:封装方法,把链接中传给后台的参数,以一个新对象的形式返回
- 知识点:
- 封装方法要封装到所属类的原型上;
- 正则表达式
var reg=/([^?=&]+)=([^?=&]+)/g;
解读:"[^?=&]"的含义是除了?,=,&这三个符号,"+"多个,"="必须要有等号; - 思路分析:第一,封装方法,this指向字符串实例对象,默认返回值为字符串实例对象;第二,封装函数执行的返回值为对象,所以需要修改构造函数中的返回值;
<script>
//需求:封装方法,把链接中传给后台的参数,以一个新对象的形式返回
//思路:创建正则表达式,利用replace方法,查找到满足规则的内容,通过在正则中添加小分组,来在回调函数中农获取参数;
var str="https://baike.baidu.com/pic/%E6%9C%B4%E4%BF%A1%E6%83%A0/3420577/0/e61190ef76c6a7eff1edd899f5faaf51f2de6641?fr=lemma&ct=single&pic=e61";
//链接中给后台传的参数,是在问号之后;
//封装方法:封装到字符串类的原型上
String.prototype.urlParse=function () {
//this代表str
var reg=/([^?=&]+)=([^?=&]+)/g;
//分析:"[^?=&]"的含义是除了?,=,&这三个符号,"+"多个,"="必须要有等号
var obj={};
this.replace(reg,function($0,$1,$2){
obj[$1]=$2;
});
return obj;//如果不填返回值,会默认返回实例对象,此时返回引用数据类型,会对其重新赋地址;
};
var obj=str.urlParse();
console.log(obj);//结果为:{fr: "lemma", ct: "single", pic: "e61"};
</script>
9. 日期格式化封装formatDate()方法
- 获取日期中的数据:
var str="2018-08-22 20:35:56"
,获取字符串中的数字信息,返回一个数组- 严格匹配:
- 思路:通过正则方法,严格制定捕获规则,通过小分组,单独获取每项信息,然后通过replace中的回调函数获取每项值,但是需要通过call方法来将arguments类数组转化为数组,然后传入参数,截取相应的项;
<script> var str="2018-08-22 20:35:56"; var reg=/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/; var ary; str.replace(reg,function(){ ary=Array.prototype.slice.call(arguments,1,arguments.length-2); }); console.log(ary);//结果为:["2018", "08", "22", "20", "35", "56"] </script>
- match方法
- 思路:制定正则方法,获取所有满足规则的内容;
<script> var str="2018-08-22 20:35:56"; var reg=/\d+/g; var ary=str.match(reg); console.log(ary);//结果为:["2018", "08", "22", "20", "35", "56"] </script>
- split方法
- 思路:制定分离方法,将字符串分割成数组;
<script> var str="2018-08-22 20:35:56"; var reg=/[^\d]+/g;//指的是非数字查找; var ary=str.split(reg); console.log(ary);//结果为:["2018", "08", "22", "20", "35", "56"] </script>
- 严格匹配:
- 利用日期模板,将日期进行转换;
- 思路:通过正则表达式中的大正则拿到被替换的内容,通过小分组拿到对应的值,作为数组的索引值,进行替换;
<script> var str="2018-08-22 20:35:56"; var strTemplate="{0}年{1}月{2}日 {3}时{4}分{5}秒"; var reg=/\d+/g; var ary=str.match(reg); var reg2=/{(\d)}/g; var str2=strTemplate.replace(reg2,function ($0, $1) { return ary[$1]; }); console.log(str2);//结果为:2018年08月22日 20时35分56秒 </script>
- 封装日期格式化formatDate()方法
<script> var str="2018-8-22 20:35:56"; //var strTemplate="{0}年{1}月{2}日 {3}时{4}分{5}秒";此时的strTemplate为默认模板,在没有传进实参时,用此模板; //封装到字符串原型上; String.prototype.formatDate=function(template){ template=template || "{0}年{1}月{2}日 {3}时{4}分{5}秒"; //含义:如果传入实参,template就为实参值,如果不传实参,那么template为undefined,给template重新赋值后面的模板; var ary=this.match(/\d+/g); var reg=/{(\d)}/g; var rem=template.replace(reg,function ($0, $1) { return ary[$1]; }); return rem;//此时返回值设置为字符串,不是this,也不默认返回this; }; var res=str.formatDate(); console.log(res);//结果为:2018年8月22日 20时35分56秒 var res2=str.formatDate("{0}年{1}月{2}日"); console.log(res2);//结果为:2018年8月22日 var res3=str.formatDate("{3}时{4}分{5}秒"); console.log(res3);//结果为:20时35分56秒 </script>
10. 知识点积累
10.1 "||"和"&&"的应用
- 知识点:
- 代码
a || b
中,若a为假,返回b;若a为真,返回a; - 代码
a && b
中,若a为真,返回b;若a为假,返回a;
- 代码
- 验证:
<script> //知识点1:"||"在用于判断时的应用 var temp="tiankong"; var mm=temp||"meihao"; console.log(mm);//结果为:"tiankong" var temp1=false;//可以是undefined,只要为假; var mm1=temp1||"meihao"; console.log(mm1);//结果为:"meihao" var temp2; var ttn=null; var mm2=temp2||ttn; console.log(mm2);//结果为:"null"; //总结:总结:代码a || b 中,1)如果a为真,则不会运行b,返回的结果为a的内容,不只是true,而是a的内容;2)如果a为假,则运行b,返回的结果为b的内容,b可以是真,也可以是假,返回的都是b;(可以是false,undefind,null); //知识点2:"&&"在用于判断时的应用 var xmp="tiankong"; var nn=xmp && "meihao"; console.log(nn);//结果为:"meihao"; var xmp1="tiankong"; var xxn; var nn1=xmp1 && xxn; console.log(nn1);//结果为:"undefined"; var xmp2; var nn2=xmp2 && "meihao"; console.log(nn2);//结果为:"undefined"; var xmp3; var xxn3=null; var nn3=xmp3 && xxn3; console.log(nn3);//结果为:"undefined"; var xmp4=(4==5); var nn4=xmp4 && xxn4; console.log(nn4);//结果为:"false"; //总结:代码a && b 中,1)如果a为假,则不会运行b,返回的结果为a的内容(可以是false,undefind,null);2)如果a为真,则运行b,返回的结果为b的内容,b可以是真,也可以是假,返回的都是b; </script>
- 实例应用:函数调用时,"||"对实参赋值与否的应用
<script> var ary=[1,2,3]; var ary1=[4,5,6]; function add(arg) { //函数中如果没有传实参,形参值就为undefined; arg=arg || ary; //含义:如果arg为真,即函数中传入实参,那么arg就为实参值;如果arg为假,即函数中没有传入实参,那么arg就为ary; console.log(arg); } add();//执行函数后,打印的结果为:[1,2,3]; add(ary1);//执行函数后,打印的结果为:[4,5,6]; </script>
10.2 正则只匹配不捕获
- 知识点:正则表达式中,添加括号会捕获为小分组内容,然后返回在数组中,现在不想捕获小分组内容,小括号的作用只是分组的作用,提高优先级;
- 代码:
var reg1=/tiankong(?:\d+)/
指的是匹配(\d+)
的内容,不获取小分组的内容;<script> var str="tiankong123"; var reg=/tiankong(\d+)/; console.log(reg.exec(str));//结果为:["tiankong123", "123", index: 0, input: "tiankong123", groups: undefined] //需求:只进行匹配,不进行捕获,即不去捕获小分组的内容;利用"?:"; var reg1=/tiankong(?:\d+)/; console.log(reg1.exec(str));//结果为:["tiankong123", index: 0, input: "tiankong123", groups: undefined] </script>
10.3 小括号的用法
- 分组
- 提高优先级:
/^(18|19)$/
;验证18或19;<script> //目的:验证18或19 var reg=/^18|19$/;//分析:1加8或1加9,以1开头,以9结尾; console.log(reg.test("18219"));//结果为true; console.log(reg.test("119"));//结果为true; //注意:当使用|的时候必须加小括号; //正确写法: var reg1=/^(18|19)$/; console.log(reg1.test("189"));//结果为false; console.log(reg1.test("18"));//结果为true; </script>
- 小分组:匹配和捕获
- 小分组:只匹配不捕获,小括号中添加
?:
;<script> var str="tiankong123"; var reg=/tiankong(\d+)/; console.log(reg.exec(str));//结果为:["tiankong123", "123", index: 0, input: "tiankong123", groups: undefined] //需求:只进行匹配,不进行捕获,即不去捕获小分组的内容;利用"?:"; var reg1=/tiankong(?:\d+)/; console.log(reg1.exec(str));//结果为:["tiankong123", index: 0, input: "tiankong123", groups: undefined] </script>
- 注意:在正则表达式中如果需要使用字符
(
和)
必须要添加转义符"";<script> var str="alpha(opacity:10)"; var reg=/alpha\(opacity:10\)/;//小括号当做字符使用时,需要加转义符; console.log(reg.test(str));//结果为:true; </script>
10.4 中括号的用法
- 中括号中不会出现两位数;只能出现一个;
<script> //[abc]意思是abc中的任何一个;不会出现两个; var reg=/^[11-89]$/;//分析:1或1-8或9,三者中的任何一个 console.log(reg.test("1"));//结果为true; console.log(reg.test("6"));//结果为true;6在1-8之间; console.log(reg.test("11"));//结果为false;11不在三者之间; </script>
- 中括号[]里面的字符意义会发生改变,分为两种
- 如"+","."这些元字符,代表加,小数点;都不用加转义符;但是在其他的时候必须加转义符才能代表加,小数点的意思;
- 对比1:
[+-]
指的是+或-,二者任何一个;此时中括号中的+号,不用加转义符,就代表加号的含义; - 对比2:
(\+|-)
指的是+或-,二者任何一个;此时在小括号中的+号需要添加转义符;才代表加号的含义;
- 对比1:
- 如"\w","\s","\d"这些元字符,带斜杠的仍然代表元字符的含义;
- 中括号和小括号的共同点:是在使用或的时候,功能是一样的;都代表两者其一;
- 中括号:
[ab]
指的就是a,b二者中任何一个; - 小括号:
(a|b)
指的也是a,b二者中任何一个; - 弊端:当a,b为数字时,必须是一位数时,才能用中括号,如果为两位数,只能用小括号;如
[1234]
代表的意思是1234四位数中的任何一个数;而(12|34)
代表的是12或34; - 注意:尽量不要用小括号,因为在exec方法捕获时,会对小括号进行小分组;会导致错乱;可以用
?:
解决;
- 中括号:
- 如"+","."这些元字符,代表加,小数点;都不用加转义符;但是在其他的时候必须加转义符才能代表加,小数点的意思;
10.5 量词元字符"?"问号的用法
-
0或1
:代表可有可无;如有效数字正则表达式中的使用;- 如:
(\.\d+)?)
代表小括号中的数据可有可无;
- 如:
- 解决正则查找中的贪婪性:放在正则捕获中的量词元字符后面
- 如:
var reg=/\d+?/g
代表捕获数字时,匹配多个数字的内容,但是在输出的时候,只输出一个数字;
- 如:
- 只匹配不捕获:用于小分组,在小分组中代码前添加
?:
;- 如:
var reg1=/tiankong(?:\d+)/
代表的意思是,只匹配到(\d+)内容,但是不会捕获(输出)小分组的内容;
- 如:
11 回调函数callback
- 定义:把函数的定义阶段,作为参数,传给另外一个函数,这个函数就叫做回调函数;
- 知识点:
- 回调函数中的this,一般为window,可以通过call改变this指向;
- callback什么时候被调用,以及被调用多少次,取决于father这个函数
- 回调函数可以传参
- 回调函数的返回值,以及赋给的函数的返回值,回调函数被调用多次,会有多个返回值,然后放在数组中,以数组形式返回给father函数;
<script> var obj={}; function f1(n,m){ console.log(this+(n+m)); return "meihao"; } function father(n){ var ary=[]; for(var i=0; i<4; i++){ /* n(2,3);//回调函数执行,传入实参;this为window;*/ n.call(obj,2,3);//改变回调函数中的this指向为obj,并且传入实参; ary.push(n(2,3));//将回调函数每次的返回值放进数组; } return ary; } var res=father(f1);//函数在定义阶段,会新建一个堆地址,然后把这个地址赋给函数名f1,此时把f1作为参数,传给father函数,则f1函数为回调函数; </script>
12 数组forEach方法
- 定义:数组forEach方法作用是遍历数组实例对象,然后执行多次回调函数,每次给回调函数传入实参;
- 知识点:
- forEach方法可以有两个参数:callback,thisArg;(第二个参数是可选的,它是用来改变this指向的);
- forEach方法中的回调函数,被调用的次数跟数组的长度一样,即遍历数组;
- 回调函数接收3个参数:item(数组中的每一项) index(索引) input(原始数组);
- forEach方法本身没有返回值;
- 第二个参数thisArg,如果不设置,则回调函数中的this一般指向window,如果设置,那么this就指向thisArg值;
- 兼容性:IE8及其以下浏览器不兼容;
<script> //检验forEach方法的返回值:如果返回值只有一个undefined,说明forEach方法没有返回值;如果接收到的是一个数组,数组元素为undefined,那么说明forEach方法有返回值,但是回调函数没有返回值; var ary=[10,20,30,40,50]; var obj={}; var res=ary.forEach(function (item,index,input) { console.log(arguments); //打印结果为五个数组,第一个数组的内容为:[10, 0, Array(5)],说明forEach会遍历数组; },obj); console.log(res);//结果为:undefined;证明forEach没有返回值; </script>
13 封装浏览器兼容的ForEach方法
- 知识点:
- 浏览器兼容与否的判断条件为:判断数组类原型上是否存在forEach属性,用in判断;
- 封装思路:分析封装方法的作用,是否需要传参数,是否有返回值;
- 封装思路:
- 封装方法,封装到所属类的原型上
- 浏览器兼容时,使用forEach方法,如果浏览器不兼容,那么使用自己封装的方法;
- 封装方法时,要了解其作用,是否需要参数,是否需要返回值
- forEach方法的作用就是多次调用回调函数,调用的次数为数组实例对象的长度,如果添加thisArg值,则在调用回调函数时,改变其this指向;
- forEach方法中,调用回调函数时,会给其传入三个实参,分别是:item数组每一项,index数组对应项的索引值, input原始数组;
- forEach方法中不需要返回值;
<script> //需求:封装forEach浏览器都兼容的方法,把ary数组克隆一份 var ary=[10,20,30,40,50]; //浏览器兼容与否,判定条件是:不同浏览器下数组类原型对象上是否存在forEach属性;即利用in来判断属性,a in b 指的是a是否为b的属性 //封装到数组类的原型上 Array.prototype.ForEach=function (callback,thisarg) { thisarg=thisarg || window;//意思为:如果传入实参,那thisarg就为实参值,如果没有传入实参,那么thisarg为window;其中window为对象; //此时this代表的是数组ary; //1)如果浏览器兼容,直接用浏览器支持的属性; if("forEach" in Array.prototype){ this.forEach(callback,thisarg); //Array.prototype.forEach.call(this,callback,thisarg);也可以写此行代码; return;//阻断程序执行;不需要返回值; } //2)不兼容的时候封装一个方法 //方法会传两个实参,一个是回调函数的定义阶段,一个是thisArg; //方法的作用,就是对回调函数进行多次调用,次数为数组实例对象的长度; for(var i=0; i<this.length; i++) { callback.call(thisarg, this[i], i, this); //没有返回值,所以不需要添加return; } }; function fn(item,index,input) { console.log(arguments); } ary.ForEach(fn); </script>
14 数组map方法
- 定义:数组map方法代码格式跟forEach方法一样,也是遍历数组,多次调用回调函数,改变回调函数this指向,但是唯一不同的是,map方法有返回值,返回值为一个数组,数组元素为回调函数每次执行后的返回值;
- 知识点:
- map方法唯一的不同是,存在返回值,返回值为一个数组,由回调函数每次执行后的返回值组成;
- map方法的其他特性跟forEach方法一样;
- map方法:IE8及其以下浏览器不兼容;
<script> var ary=[10,20,30,40,50]; var res=ary.map(function (item, index, input) { return item+index; }); console.log(res);//结果为:[10, 21, 32, 43, 54] </script>
15 封装浏览器兼容的Map方法
- 知识点:
- 与forEach方法不同点,map方法具有返回值;
<script> var ary=[10,20,30,40,50]; //封装方法要在所属类的原型上封装 Array.prototype.Map=function (callback, thisarg) { thisarg=thisarg || window; if("map" in Array.prototype){ return this.map(callback,thisarg); } var ary1=[]; for(var i=0; i<this.length; i++){ var rem=callback.call(thisarg,this[i],i,this); ary1.push(rem); } return ary1; }; function fn($1,$2) { return $1*$2; } var res=ary.Map(fn); console.log(res);//结果为:[0, 20, 60, 120, 200] </script>