资讯专栏INFORMATION COLUMN

【愣锤笔记】一支穿云箭、正则来相见

wangbjun / 1647人阅读

摘要:表示进行多行匹配。如果正则表达式中含有子表达式,那么该数组后续的项依次为匹配到的第一个子表达式的匹配结果,第二个第个。关于正则方法有一点必须要提,很容易导致错误的情况。这时候直接使用该正则表达式对进行方法调用,却返回了。匹配前一项至少次。

有人说,一行正则抵得上100行代码……

正则表达式,每门语言都有,在我们的js开发中,最常见的使用场景:一是表单验证,像是登录注册啊,用户输入检测啊,不管在前台项目还是后台管理系统,都会经常使用;二是,在开发一些重数据交互的后台管理系统或者应用的时候,更是会大量的使用,各种字符匹配,表达式检测等等。

正则本身知识点不是很多,但是由于各种字符意思容易忘记,所以需要经常复习,多使用就记住了。

创建一个正则表达式:

// 通过RegExp构造函数创建
var regex1 = new RegExp("[a-z]", "g");
// 通过直接字面量创建
var regex2 = /[a-z]/g;

这两种方式都可以创建正则表达式,以上两种方式创建了一个等价的正则表达式,均为匹配字母a到z。但是日常开发中,基本都是通过直接字面量创建:两个反斜杠之间为正则表达式,反斜杠后面跟着修饰符i、g、m。修饰符可写可不写,也可以同时写多个,他们的意思分别是:

i:表示忽略大小写,就是在字符串匹配的时候不区分大小写。
g:表示全局匹配,即所有满足的字符都会被匹配到,一直匹配到字符串的结尾。
m:表示进行多行匹配。这个是什么意思呢,举个例子吧:

var str = "hello world 
 my name is LengChui."

可看到这个字符串中有一个 换行符,正常匹配时,到 就结束了,也就是只会匹配到这一行的结尾。但是如果加了m修饰符,会继续往后面匹配,一直匹配到字符串的最终结尾。

当然了,修饰符可以同时写多个,例如:var regex = /[a-z]/ig;表示匹配所有的字母a到z,且不区分大小写。这样,对于字符串"a123H"就会匹配到a和Z


正则表达式方法:test()和exec()

所有的正则表达式都有test和exec这两个方法。

test()方法:测试字符串中是否包含了匹配该正则表达式的子串,如果包含了这样的子串,那么返回true,否则返回false

// 定义一个匹配hello字符串的正则表达式
var reg = /hello/g;
var str = "hello world";
// 如果字符串str中匹配到了hello字符串,则打印如下信息
if (reg.test(str)) {
    console.log("字符串str中含有hello子串")
}

这个方法相信在验证用户输入内容的时候,会经常使用到。例如,相信很多人写过类似下面的正则验证用户输入值的合法性代码:

// 点击提交按钮,验证输入值,提交ajax请求
document.getElementById("submitButton").addEventListener("click", function (event) {
    // 获取用户输入的手机号
    var phoneNumber = document.getElementById("phone");
    // 验证手机号格式的正则
    var regPhone = /^1[3|4|5|8]d{9}$/g;
    // 检测输入的合法性,进行错误提示
    if (!phoneNumber) {
        $tim("请输入手机号!")
        return;
    }
    if (!regPhone.test(phoneNumber)) {
        $tip("手机号格式不正确,请重新输入!");
        return;
    }
    // 如果验证成功,提交ajax请求
    $.ajax(………………)
}, false);


exec方法:接收一个参数,即待检测的字符串。它返回一个增强的数组对象,数组的第一项为匹配到的字符串。如果正则表达式中含有子表达式,那么该数组后续的项依次为匹配到的第一个子表达式的匹配结果,第二个……第n个。如果没有匹配到任何内容,则返回null。

通过例子来说明exec的使用方法:

// 定义一个字符串
var str = "hello javascript, hello javaspring"
// 定义一个正则表达式,该表达式匹配任意java后跟任意大小写字母的字符串
// 注意这里的正则表达式没有加g,后面会说明exec的正则表达式加g与不加g的区别
var reg = /java([a-zA-Z]+)/;
// 调用exec方法
var execResult = reg.exec(str);
console.log(execResult)

看下最终的打印结果:


可以看到返回一个数组,数组的第一项为匹配到的结果,第二项为第一个子表达式的匹配结果,如果还有其他子表达式,会依次往后排。同时这个数组对象还有以下几个属性:

    groups: undefined

    index// 当前匹配结果的开始下标。这里匹配的javascript字符串的开始下标为6。

    input // 待匹配的字符串,其实就是我们的这里的str字符串

注意上述正则表达式/java([a-zA-Z]+)/没有加修饰符g,这意味着不需要全局匹配。这种情况下,exec()方法只会匹配依次便最终匹配结束了,那么如果继续调用execResult = reg.exec(str);,则会重新开始匹配,即从字符串0的位置开始重新匹配并返回新的匹配结果。其结果肯定是一样的。如下面例子:

var str = "hello javascript, hello javaspring"
var reg = /java([a-zA-Z]+)/;
// 第一次匹配调用并打印结果
var execResult = reg.exec(str);
console.log(execResult);
// 重新调用并打印结果
execResult = reg.exec(str);
console.log(execResult);


可以看到两次调用的匹配结果是一样的。这里不禁就有人说了,那不是废话了,调用同一个表达式,结果不就一样嘛。然而,还真不是。在介绍这个之前,我们先简单提一下正则表达式的实例属性,告诉了我们该正则表达式的一些基本信息。这个不需要记,了解一下即可:

var reg2 = /a/igm; // 定义一个不区分大小写、全局匹配、多行匹配字符串a的正则表达式
console.dir(reg2) // 打印出该对象


下表中列出了所有的正则表达式实例属性。

实例属性含义
globalBoolean值,指明正则表达式是否包含g修饰符
ignoreCaseBoolean值,指明正则表达式是否包含i修饰符
lastIndex

若正则表达式包含g修饰符,该属性指明执行exec()test()方法后,最后一次匹配结果字符串后面的第一个字符的位置

source只读属性,给出了正则表达式的内容,即除了斜杠和选项字符之外的整个正则表达式。
multilineBoolean值,指定搜索字符串时是否跨行搜索,即是否包含m修饰符,该属性的另外一个名称是$*

了解了这个之后,我们回过头来继续说exec()方法。在调用exec()方法的正则表达式没有加修饰符g,即不是全局匹配的模式下,每次调用exec()之后,本次的正则匹配也就最终结束了,注意是最终结束了。下次该正则表达式再次调用exec()方法时会从字符串开头开始匹配,可以立即为开始了一次新的正则匹配。

那么如果调用exec()方法的正则表达式是全局匹配的话(加了修饰符g),该正则表达式每次调用exec()方法结束后,其实例属性lastIndex都会指向本次匹配结果字符串后面一个字符的位置,直到匹配结果返回null,即没有匹配到任何结果的时候,才会将其lastIndex属性重置为0。继续看这个例子演示:

var str = "hello javascript, hello javaspring"
// 定义匹配任何java后跟任意大小写字母的字符串,注意这里是全局匹配
var reg = /java([a-zA-Z]+)/g;

// 该正则表达式第一次调用exec()方法并打印匹配结果和其实例属性lastIndex
var execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);

// 第二次调用
execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);

// 第三次调用
execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);


从打印结果可以看出,第一次匹配到了字符串javascript,其开始下标为6,实例属性lastIndex16,即javascript字符串后面的一个字符“逗号”的位置下标。第二次调用的匹配结果为javaspringlastIndex的值为34。第三次调用没有匹配到任何结果,所以返回了null,其lastIndex的结果也被重置为了0

关于正则方法exec()有一点必须要提,很容易导致错误的情况。当调用exec()方法的正则表达式是全局匹配的情况下,对一个字符串匹配后,如果没有匹配到最终结果,即没有返回null的情况下,使用该正则表达式对新字符串进行exec()方法调用时,切记一定要先将该正则表达式的实例属性lastIndex重置为0。看例子:

var str = "hello javascript, hello javaspring"
var str2 = "javascript and html"

// 定义匹配任何java后跟任意大小写字母的正则表达式,全局匹配
var reg = /java([a-zA-Z]+)/g;

// 使用该正则的exec()方法匹配字符串str
var execResult = reg.exec(str);
console.log(execResult, reg.lastIndex);

// 使用该正则的ecev()方法匹配字符串str2
execResult = reg.exec(str2);
console.log(execResult, reg.lastIndex);


从打印结果可以看出,对于str字符串的正则匹配时,正常返回了结果,其lastIndex的值为16,还并没有最终匹配结束,lastIndex值也没有重置为0。这时候直接使用该正则表达式对str2进行exec()方法调用,却返回了null。为什么呢,正常应该也可以匹配到str2字符的javascript字符啊。这是因为,对str调用后,其lastIndex值被赋值为了16,那么下次对str2调用的时候,便从下标16开始调用,str2中从下标16开始匹配自然而然是没有匹配到任何字符串。注意,正则表达式的实例属性lastIndex是可读可写的属性,所以为了避免这种情况,在对str2正则匹配前,先将其lastIndex属性重置为0

reg.lastIndex = 0;
execResult = reg.exec(str2);
console.log(execResult, reg.lastIndex);


元字符

所谓元字符,其实就是在正则表达式的不同上下文中有着特殊意义的标点符号,请看下面:

. * + ( ) $ /  ");

嗯~没错,就是这几个字符,通过不同的组合可以帮我们构建出非常强大的正则表达式。注意,这些字符带有特殊意义,如果就只是单纯的项匹配这些字符,需要加/进行转义,例如.就只是匹配一个点,没有其他特殊意义。下面我们一一进行介绍。

. : 匹配除了换行符和回车之外的任何字符,eg: /./ 匹配一个除换行回车之外的任意字符;

[] :  匹配方括号里面的任意字符。方括号内可以是1个字符也可以是多个字符。eg: [ab] 匹配字符a,也可以匹配字符b;[a- z] 可以匹配字母a到z任意一个,-表示的意思;[0-9]可以匹配数字0到9;也可以混合使用[a-zA-Z0-9]可以匹配小写字母a到z,大写字母A-Z,可以匹配数字0-9;

[^] : 匹配除了方括号内^后面的任意字符,可以理解为[]的取反操作。eg: /[^ab]/ 匹配除了a和b以外的任意字符。 

| : 或,即匹配 | 左边或者右边的表达式。eg: /a|b/ 匹配字符a或者字符b

: 匹配0个或多个前面的表达式, eg: /a*/ 匹配0或者多个a,a、aa、aaa、aaaa等都是满足匹配规则的。

+ : 匹配1个或多个前面的表达式,和*类似,但是至少要满足匹配一次。eg: /a+/ 可以匹配1个或多个a,隐藏a、aa、aaa等都是合法的,但是bcdf是不符合匹配规则的,因为没有至少匹配到一个a。

");:  匹配0和或1个前面的表达式,可以理解为前一项是可选的。和*+类似,但是要注意三者的区别。

{n, m} : 匹配前一项n到m次,包含n次和m次。eg: /[0-9]{6,8}/ 可以匹配6到8位数字。

{n, } :  匹配前一项至少n次。 eg: /[0-9]{11, }/ 至少匹配11位数字

{n} : 匹配前一项n次。 eg: /[0-9]{5}/  匹配5位数字

需要注意的是:*");可以匹配前一项0次,因此像类似 /a*/.test("bcdf") 是返回true的,因为他匹配到了0个a;而/a*/.exec("bcdf")也是返回了一个第一项是一个空字符串的数组,而不是返回null,也是因为匹配了0个a。

另一个需要注意的是,正则匹配默认都是贪婪匹配。什么意思呢?就是尽可能多的匹配,比如用/a+/来匹配字符串aaabbbb时,会匹配到aaa,即尽可能多匹配。类似的重复匹配时都是贪婪匹配的。然而可以使用这些元字符加上");/a+");再对aaabbbb匹配时,则只会匹配到一个a,其他的*");  {}"); ");同理。

: 和一些字符组合使用会有特殊的意义:

w元符号,等价于[a-zA-Z0-9_],匹配任何字母、数字、下划线字符,这样的字符也称为单词字符
W元符号,等价于[^a-zA-Z0-9_],匹配除了字母、数字、下划线字符之外的任何字符
d元符号,等价于[0-9],匹配任何单个的数字字符
D元符号,等价于[^0-9],匹配除了数字之外的任何单个字符
s元符号,匹配空白字符,即空格、Tab字符和回车换行符
S元字符,匹配任何非空白字符

^ :匹配字符串的开始位置,或多行匹配模式中(即加了修饰符m)每一行的开始位置

$ : 匹配字符串的结束位置,或多行匹配模式下(即加了修饰符m)每一行的结束位置

^$这两个元字符,在日常开发中几乎是最常见的了,几乎大部分的正则表达式都是这种形式的:/^表达式$/。都知道是它的意思是匹配字符串的开始和结束为止,猛一看好像理解了,但是细细揣摩貌似又不知道到底是什么意思。下面我就细细说来:

这两个字符和上面其他元字符不同的是,这个字符匹配的是位置,而不是具体匹配的某个字符。这么说,应该清晰一点了,所以/^表达式$/就是从字符串开头的位置开始,一直到结束的位置,都必须满足匹配规则才行。再次强调下,^$匹配的都只是一个位置,位置,位置。

 : 匹配单词边界。这个也是用来匹配位置的,通俗的讲,就是匹配区分单词分割位置的。例如,两个单词之间的位置,第一个单词前面的位置,最后一个单词后面的位置,都是匹配的单词位置。eg: /java/可以匹配单词java,即匹配java字符两边都是单词边界的结果,对于字符串I love java very much则匹配成功,而字符串I love javascript very much则匹配不成功。因为第一句的java两边空格都是单词边界,而javascipt虽然包含了java单词,但是只满足左边是单词边界,其子串java的右边是script子串,而不是单词边界,所以不满足两边都是单词边界的匹配规则。

console.log(/java/.test("java")) // true
console.log(/java/.test("javascript")) // false

B:匹配非单词边界,是的反义词。eg:/Bscript/ 对于字符串javascript是可以匹配成功的,因为其子串script的左侧是java字符串,不是单词边界。而对于字符串script则是不成功的,因为其左侧什么都没有,即左侧就是一个单词边界。

console.log(/Bscript/.test("javascript")) // true
console.log(/Bscript/.test("script")) // false


断言

js里面的断言只支持先行断言,又分为正向先行断言负向先行断言。这么说比较绕口,让人云里雾里的感觉,所以还是直接上例子:

");: 正向先行断言,其实就是说");/java(");只能匹配javascript,不能匹配javaspring,java123等等。

");: 负向先行断言,即");/java("); 只能匹配javaspring,java123等等,但不能匹配javascript。


分组/子表达式

() : 子表达式,也可以叫分组,就是把括号里面的表达式作为一个整体来处理。一个正则表达式里面可以有多个子表达式,子表达式里面也可以嵌套子表达式。在我们介绍exec()方法的时候说过,exec()返回一个增强的数组,数组第一项为该正则表达式的匹配结果,第二项及以后为对应的子表达式的匹配结果。

// 没有子表达式的正则exec()方法
var reg1 = /[a-z][0-9]/;
var str1 = "hello123";
console.log(reg1.exec(str1))

// 添加了子表达式的正则exec()方法		
var reg2 = /([a-z])([0-9])/;
var str2 = "hello123";
console.log(reg2.exec(str2))

// 子表达式嵌套的情况
var reg3 = /(([a-z])([0-9]))/;
var str3 = "hello123";
console.log(reg3.exec(str3))


打印结果可以看出,加子表达式之后,比没加之前多返回了几项,这几项分别对应每个子表达式匹配的结果。注意,当有嵌套的情况下,子表达式的顺序,其实就是所有的左括号从左到右出现的顺序。

每一子表达式匹配到的值都会被保存下来,分别存在1,2,3……里面,也会保存在$1,$2,$3……两者的区别是,1这种类型的是使用在正则表达式中的,$1这种类型的是使用在字符串的方法中。关于字符串方面会在文章后面的内容讲解。先看个例子吧:

// 需要匹配第一第二位都是数字,第三位和第一位必须相同,第四位和第二位必须相同的正则表达式
var reg4 = /(d)(d)12/;
// 打印为true,因第一位和第二位都是数字,第三位和第一的值相同,第四位和第二位的值也相同
console.log(reg4.test("1212")) // true
// 打印结果为false,因为第三位的值和第一位的不一样
console.log(reg4.test("1232"))

从这正则表达式可以看到,要求匹配的第一位和第二位都是数字,那么后面的1和2是什么意思呢,就是说1就是第一个(d)匹配到的结果,2就是第二个(d)匹配到的结果。注意,这里的意思并不是说第三位第四位是和第一第二位匹配的规则相同的,而是说,加入第一位匹配到了数字2,那么第三位也只能数字2,如果第二位匹配到了数字4,那么第四位也必须是4才可以。那么最终的匹配结果就是类似1212, 4747等。eg: 左引号和右引号必须相匹配的情况,可以这样子:/[""][^""]*1/,即首先是单引号或者双引号,后面是0到多个非单引号双引号字符,最后如果第一个匹配了单引号则最后一个必须是单引号,如果第一个匹配到了双引号则最后也必须是双引号。

注意在子表达式嵌套的情况下,1,2……对应的其实就是左括号的值,不管它怎么嵌套。这么说应该更好理解了。

那么问题来了,如果不想保存子表达式的值呢,或者说多个子表达式中我不想保存某些子表达式的值怎么办呢?

("); : 一个问号加一个冒号,成为无记忆匹配。他依然是对括号中里面的内容进行分组,但是不会捕获子模式,即不会保存匹配到的值到1,2,3……中。现在我修改一下上面的例子再看:

// 需要匹配第一第二位都是数字,第三位和第二位必须相同
var reg4 = /(");false,因第一位和第二位都是数字,第三位和第二位的值不一样
console.log(reg4.test("1212"))
// 打印结果为true,因为第三位的值和第二位的值相同
console.log(reg4.test("1232"))

从表达式可以看出,我们的第一个(");子表达式添加了无记忆匹配模式,所以后面的1里面存放的值就变成了后面的(d)匹配的结果。因此,子表达式设置了无记忆匹配模式后,1,2……便不会再存储其匹配结果了,而是存储后面没有设置无记忆匹配模式的子表达式。


字符串方法中正则表达式的运用

字符串方法小伙伴们都很熟悉,这里只说和正则匹配相关的方法。正则表达式本身就是用来处理字符串的匹配规则,那么相应的字符串方法,当然得和正则勾搭点关系啦~~好了,拉回正题,下面先列举和正则有关的字符串方法:

match(regex)返回所有与正则表达式regex相匹配的子串数组
replace(regex,replacement)字符串替换。将字符串中的regex指定的子串替换为子串replacement
search(regex)字符串搜索。查找正则表达式regex指定的模式在字符串中的开始位置
split(regex)字符串分割。使用正则表达式regex分割字符串,并将分割的结果以数组的形式返回

  (1) match方法:返回一个由匹配结果组成的数组,如果没有匹配到任何结果则返回null。该方法接收一个正则表达式作为参数,如果不是正则表达式,它会首先调用new RegExp()将参数转换成正则表达式。

注意:如果正则参数不带修饰符g,match方法不会进行全局匹配,其效果和不加修饰符g的exec()方法返回的结果是一样的。如果忘记了exec()方法,可以往回翻翻回顾一下。

"aaaa".match("b") // 返回null,因为没有匹配到任何内容

下面看下正则表达式不带修饰符g的例子:

console.log("abcd");.match(/a/)) 


在不是全局匹配的情况下,其返回结果和exec()方法如出一辙,如果表达式含有子表达式的话,数组的第二项及后续项是子表达式的匹配结果。如果是全局匹配的话,则会返回一个由所有匹配结果组成的数组:

// 不含有子表达式的全局匹配
console.log("1a2b3c4d5");.match(/[0-9]/g))

// 含有子表达式的全局匹配
console.log("1a2b3c4d5");.match(/[0-9]|(a)/g))


结果非常的直观,在全局匹配模式下会返回所有匹配结果组成的数组。但是如果正则表达式含有子表达式的话,也会把子表达式的匹配结果返回出来。

  (2) replace()方法:用于字符串的替换,并返回替换后的结果。接收两个参数,第一个参数是匹配的规则,第二参数是用来替换的字符串。第一个参数,可以是字符串,也可以是正则表达式。

字符串就不多说了,这里只说是正则表达式的情况,replace会根据正则表达式去匹配对应的结果,然后将其替换成第二参数:

// 正则表达式不带修饰符g
console.log("abc1234".replace(/[a-z]/, "0"))
// 正则表达式带修饰符g
console.log("abc1234".replace(/[a-z]/g, "0"))


输出结果可以看出,在不加修饰符g的情况下,字符串的repalce方法不会全局检索替换,而只是替换了第一次。在全局匹配模式下,replace方法会把所有的匹配结果全局替换成第二个参数对应的字符串。

前文说子表达式的时候说到,正则表达式会把匹配结果存放在类似1,2$1,$2的里面,在这里便可以用到$1,$2了。用法就是,在repealce()方法的第二个参数字符串中,$1,$2……不再是普通的字符串,而是有着特殊一样的标识符,对应的值就是正则表达式每一个子表达式匹配到的结果:

// 定义一个匹配一个abc字符后面跟着一个数字的正则表达式
// 并将匹配结果替换成该子表达式的结果
console.log("abc1234".replace(/abc(d)/g, "$1")) // 1234

该替换方法,最终将abc1替换成了第一个子表达式匹配的结果1,所以最终结果是1234。

repalce()方法的第二次参数,不仅可以是字符串,还可以是一个函数,如果是函数则对每一次的匹配结果调用该函数。该函数必须返回一个字符串,如果没有reutrn语句,则是跟正常函数一样默认返回undefined。如果返回的不是字符串类型,会将其转换成字符串类型:

console.log("abc1234".replace(/abc(d)/g, function(){ 
    return "hello"
}))
// 打印结果为hello234

从结果可以看出,将匹配到的字符串abc1替换成了hello字符串。

同时,该函数有多个参数,第一个参数是当前匹配到的结果,第二个参数开始往后是子表达式匹配到的结果,可以有0-n个。再后面一个参数当前匹配结果在原字符串中的下标,最后一个参数原字符串:

"abc1234".replace(/abc(d)(d)/g, function(a,b,c,d,f){
    console.log(a,b,c,d,f)
})
// 打印结果为 abc12 1 2 0 abc1234

可以看到打印的结果abc12是正则匹配到的结果,1是第一个子表达式(d)匹配的结果,2是第二个子表达式(d)匹配到的结果,0是匹配结果字符串在原字符串中的下标,abc1234是原字符串。再看下匹配到多次结果的情况:

"abc1234abc567".replace(/abc(d)(d)/g, function(a,b,c,d,f){ 
    console.log(a,b,c,d,f)
})
// 下面是打印结果
abc12 1 2 0 abc1234abc567
abc56 5 6 7 abc1234abc567

对于有多次匹配结果的情况,会多次调用该函数。

  (3) search()方法查找匹配结果在原字符串中的位置。接收一个字符串或者正则表达式作为查询参数。最终返回查询到的下标,没有查询到则返回-1。

// 参数为字符串时
console.log("abcd".search("d")) // 3

// 参数为正则表达式
console.log("abcd".search(/d/)) // 3

上面演示了简单的查找,对于简单的查找,完全是可以使用字符串的indexOf()方法,查找结果都是一样的。

console.log("abcd".indexOf("d")) // 3

需要注意的地方就是:1.该方法不会进行全局查找,即会忽略修饰符g,一旦匹配到结果即返回下标; 2.会忽略正则表达式的lastIndex属性,即每次查找都从字符串开始位置重新开始。

var str = "abcddadd"
// 只返回了第一个d字符的洗标,忽略修饰符g
console.log(str.search(/d/g)) // 依旧输出了3

// 第二次调用,依旧输出3,即忽略了lastIndex属性
console.log(str.search(/d/g))

  (4) split()方法: 用于字符串分割,接收一个用于分割字符串的字符串或者正则表达式作为参数,第二个参数为可选的指定返回分割后的数组长度。

// 第一个参数为""时, 将按字符分割字符串
// 这在我们需要把字符串作为组数处理时非常有用
"asdfg".split("") // ["a", "s", "d", "f", "g"]
// 可以接收第二参数,作为返回后的数组长度
"asdfg".split("", 3) // ["a", "s", "d"]
// 以字符串s进行跟个
"asdfg".split("s") // ["a", "dfg"]
// 以正则表达式匹配结果进行分割
"asdfg".split(/s/) // ["a", "dfg"]

比如下面,一个简易版的解析url中键值对参数

/*
 * 简易解析url中键值对参数
 * @param url { String } 待解析的url
 * @return { key1: 1, key2: 2} 返回解析后的键值对的对象
 */
const parseQueryString = url => {
    if (!url) throw Error("缺少待解析url")
    let result = {}
    const query = url.split("");)[1]
    query && query.split("&").forEach(e => {
        const parts = e.split("=");
        result[parts[0]] = parts[1];
    })
    return result;
}

parseQueryString("www.baidu.com");) // {ke1: 1, key2: 2}

那就再扯一下数组的join()方法吧,可以理解为字符串split()方法的反作用方法。该方法用于将数组转换成字符串,接收一个参数,作为拼接符,默认是英文逗号:

[1,2,3,4,5].join() // "1,2,3,4,5" // 默认逗号拼接
[1,2,3,4,5].join("a") // "1a2a3a4a5" // 自定义用字符a拼接



文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7013.html

相关文章

  • 2021年安全类公众号合集

    摘要:网安杂谈公安部网安局中国信息安全网络安全联盟三六零奇安信绿盟科技快识先森杂术馆安全鸭黑战士小刚安全安译已注销国产笔记边界安全阿乐你好乌雲安全之道学蚁致用长安刺客信安本原信安随笔骨哥说事小迪安全安全猎人已注销星晴安全亿人 ...

    simpleapples 评论0 收藏0
  • 愣锤笔记】MVVM时代下仍需掌握的DOM - 基础篇

    摘要:然而,操作作为前端的基础,自诞生以来便左右着我们的页面效果。不管任何时候,依旧是前端必须掌握且需要投入一定时间研究的基础。不能只停留在事件的操作或者只是掌握那几个最常见的。在当前MVVM大行其道的环境下提到DOM一词,很多人可能会感到有些诧异。这种差诧异或许来自于类似都什么年底了还操作DOM啊的声音!说的没错,MVVM时代,虚拟dom东征西战,一枝独秀,着实不可否认其强大的威力。 然而,DO...

    callmewhy 评论0 收藏0
  • 分享AI有道干货 | 126 篇 AI 原创文章精选(ML、DL、资源、教程)

    摘要:值得一提的是每篇文章都是我用心整理的,编者一贯坚持使用通俗形象的语言给我的读者朋友们讲解机器学习深度学习的各个知识点。今天,红色石头特此将以前所有的原创文章整理出来,组成一个比较合理完整的机器学习深度学习的学习路线图,希望能够帮助到大家。 一年多来,公众号【AI有道】已经发布了 140+ 的原创文章了。内容涉及林轩田机器学习课程笔记、吴恩达 deeplearning.ai 课程笔记、机...

    jimhs 评论0 收藏0
  • 7月份前端资源分享

    摘要:更多资源请文章转自月份前端资源分享的作用数组元素随机化排序算法实现学习笔记数组随机排序个变态题解析上个变态题解析下中的数字前端开发笔记本过目不忘正则表达式聊一聊前端存储那些事儿一键分享到各种写给刚入门的前端工程师的前后端交互指南物联网世界的 更多资源请Star:https://github.com/maidishike... 文章转自:https://github.com/jsfr...

    pingan8787 评论0 收藏0
  • 让人相见恨晚的vim插件:模糊查找神器LeaderF

    摘要:是什么是一个用写的插件,可以在成千上万数十万个文件中,通过模糊查找的方式,快速找到目标文件。它还有很多衍生功能快速打开或定位某个最近使用的文件包括函数类变量等命令历史文件中的某一行的等等。友情链接,也許是最好的模糊查詢插件 提到vim的模糊查找插件,很多人第一反应是ctrlp.vim,ctrlp知名度很高,但跟其它的同类插件相比,它的唯一优点是用vimL编写(这让它的性能是所有同类插件...

    Near_Li 评论0 收藏0

发表评论

0条评论

wangbjun

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<