题目描述:
1. 指定参数名称,返回该参数的值 或者 空字符串
2. 不指定参数名称,返回全部的参数对象 或者 {}
3. 如果存在多个同名参数,则返回数组
示例:
输入:http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe
输出:[1, 2, 3]
解答:
function getUrlParam(sUrl, sKey) {
var result = {};
sUrl.replace(/\??(\w+)=(\w+)&?/g, function(match, p1, p2) {
if(result[p1] === void 0) {
result[p1] = p2;
} else {
var t = result[p1];
result[p1] = [].concat(t, p2);
}
});
if(sKey === void 0) {
return result;
} else {
return result[sKey] || '';
}
}
分析:
首先说明一下,这段代码不是自己写的,之所以写到这里也仅是为了学习,把不懂得地方记录下来。
这段代码刚看时没怎么看懂,然后就在MDN上一顿查啊,好不容易弄懂了之后再看代码,卧槽!被惊艳到了有木有(如果惊艳这个词可以这么用的话)。咳咳,,,好了,不说废话了,上解释。
- 首先要说的就是字符串的
replace()
方法,直接看这里吧 String.prototype.replace(),MDN上已经写得很详细了。这里的replace()
方法,第一个参数用的是一个RegExp
对象,该正则所匹配的内容会被第二个参数的返回值替换掉;第二个参数用的是一个function
,该函数的返回值将替换掉第一个参数匹配到的结果。需要指出的是,如果第一个参数是正则表达式, 并且其为全局匹配模式, 那么第二个参数的函数将被多次调用, 每次匹配都会被调用,正是因为这样,才有了使用行内函数和正则来避免循环 的操作,也就是上述链接的最后一节。 - 接下来要说的就是正则表达式了,也可以看MDN这里 正则表达式,自问自己写的肯定不如这里详细。
- 再接下来就是
void 0
了,据说一些老司机在用到undefined
时,为了避免直接使用undefined
会被重写掉,就会用void 0
,这个具体也可以看MDN void 运算符。 - 最后要说一下
[].concat(t, p2);
,为什么不直接用t.concat(p2);
,因为这里要得到的是一个数组而不是字符串,而t
的第一个值是字符串,字符串的concat()
方法返回的还是一个字符串,数组的concat()
方法返回的才是数组,而且数组的concat()
方法参数可以是数组和/或值。具体还是可以参见 String.prototype.concat() 和 Array.prototype.concat() (有木有发现MDN是个好东西?)。