解析30 seconds of code网站代码片段之「获取URL参数」
获取URL参数
const getURLParameters = (url) =>
(url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
(preVal, curVal) => (
(preVal[curVal.slice(0, curVal.indexOf('='))] = curVal.slice(curVal.indexOf('=') + 1)), preVal
),
{}
);
流程解析
- 通过
String.prototype.match()方法匹配到所有参数的键值对; - 通过
Array.prototype.reduce()将参数键值对全部整合在一个对象中; window.location.search取到URL中?后的参数字符串可以作为参数传给函数getURLParameters的url参数。也可以直接传递整个url链接字符串。
技术解析
输入:URL字符串
输出:参数对象
match
match方法:match(reg)根据正则reg将字符串分割后返回数组,如果全部都匹配不到就返回null。
正则表达式
[^?=&]:[]表示或,类似|,[^]表示查找?=&字符之外的字符;后面的=[^&]表示将参数中的值带上=的符号;
// 一般url格式http://url.com/page?name=Adam&surname=Smith
// 首先是?+&之外并且有=,或者&之外:name=Adam,surname=Smith
url.match(/([^?=&]+)(=([^&]*))/g)
reduce
reduce方法:reduce(callback, initVal)方法用以做累加的操作。initVal表示初值,callback函数里的参数固定function(preVal, curVal, index, array) { ... }分别表示之前的值/当前的值/当前值的索引/当前操作的数组本身。
reduce会遍历数组的每一个元素,每一次遍历的结果作为preVal,下一个元素为curVal,依次循环。
// 本例的结构可以看出初始值是空对象,也就是初始时preVal={}
arr.reduce(
(preVal, curVal) => {...},
{}
)
箭头函数
箭头函数的规则:
- 如果只有一条语句可以不用写
{}和return。 - 没有
{}时=>和函数体必须在同一行,不能换行。可以利用()进行换行。
// 本例利用()换行
(a, v) => (
....
);
// 等价于
(a, v) => {
return ....
}
// 等价于
(a, v) => ....
逗号操作符
逗号操作符,:对每个操作数求值(从左到右)并返回最后一个操作数的值。当你想要在期望一个表达式的位置包含多个表达式时,可以使用逗号操作符。
let x = 1;
x = (x++, x); // 2
let fn = () => (1,2,3);
fn(); //3
在本例中:
// preVal[curVal.slice(0, curVal.indexOf('='))] = curVal.slice(curVal.indexOf('=') + 1
// 上面一串代码作用是将URL参数键值对一一对应放入对象
(......, preVal) //最终返回preVal的值
结合到箭头函数可能有点不太好懂,括号里面套括号,其实第一层括号为了换行,第二层括号是为了一行多操作表达式。
flush points
在动态语言里使用任何方法都要考虑边界条件。很容易出现运行时出错。
url.match(/([^?=&]+)(=([^&]*))/g) || []中,match匹配不到字符串返回null,如果没有|| []程序就会抛出错误停止执行,因为null没有reduce方法。
thinking
这样子写程序在工作中应该会被打吧。。。。太简化了,没有注释真的不太好懂
简化了一下:
const getURLParameters = (url) => {
const urlParamArr = url.match(/([^?=&]+)(=([^&]*))/g) || [];
const urlParamObj = urlParamArr.reduce(
(preVal, curVal) => {
preVal[curVal.slice(0, curVal.indexOf('='))] = curVal.slice(curVal.indexOf('=') + 1);
return preVal;
},
{}
);
return urlParamObj;
}