最近在补充基础知识,看到了一道面试题 地址传送点这里 :git
答案:github
/**
* 解析一个url并生成window.location对象中包含的域
* location:
* {
* href: '包含完整的url',
* origin: '包含协议到pathname以前的内容',
* protocol: 'url使用的协议,包含末尾的:',
* username: '用户名', // 暂时不支持
* password: '密码', // 暂时不支持
* host: '完整主机名,包含:和端口',
* hostname: '主机名,不包含端口'
* port: '端口号',
* pathname: '服务器上访问资源的路径/开头',
* search: 'query string,?开头',
* hash: '#开头的fragment identifier'
* }
*
* @param {string} url 须要解析的url
* @return {Object} 包含url信息的对象
*/
function parseUrl(url) {
var result = {};
var keys = ['href', 'origin', 'protocol', 'host',
'hostname', 'port', 'pathname', 'search', 'hash'];
var i, len;
var regexp = /(([^:]+:)\/\/(([^:\/\?#]+)(:\d+)?))(\/[^?#]*)?(\?[^#]*)?(#.*)?/;
var match = regexp.exec(url);
console.info('match=', match);
if (match) {
for (i = keys.length - 1; i >= 0; --i) {
result[keys[i]] = match[i] ? match[i] : '';
}
}
console.info('result=', result);
return result;
}
parseUrl("http://test.com:8080?name=1&password=2#page1");
结果:
match=[
'http://test.com:8080?name=1&password=2#page1',
'http://test.com:8080',
'http:',
'test.com:8080',
'test.com',
':8080',
undefined,
'?name=1&password=2',
'#page1',
index: 0,
input: 'http://test.com:8080?name=1&password=2#page1'
]
result={
hash: '#page1',
search: '?name=1&password=2',
pathname: '',
port: ':8080',
hostname: 'test.com',
host: 'test.com:8080',
protocol: 'http:',
origin: 'http://test.com:8080',
href: 'http://test.com:8080?name=1&password=2#page1'
}
复制代码
没错,一眼就看到了难以理解的是那段正则表达式:面试
/(([^:]+:)\/\/(([^:\/\?#]+)(:\d+)?))(\/[^?#]*)?(\?[^#]*)?(#.*)?/
复制代码
恰好最近看了精通正则表达式一书(的20%,哈哈看不完),恰好能够练练手了正则表达式
首先,在分析以前,先给你们补补基础概念,知道的就跳过数组
?: 匹配0个或一个
* 匹配0个或多个,
+: 一次或屡次,至少出现一次
.* 贪婪匹配:在知足匹配时,匹配尽量长的字符串,默认状况下,采用贪婪匹配(没有问号)
// 非贪婪匹配:在知足匹配时,匹配尽量短的字符串,使用?来表示非贪婪匹配
? 非贪婪,最小匹配(重点,后面会用到)
*? 重复任意次,但尽量少重复
+? 重复1次或更屡次,但尽量少重复
?? 重复0次或1次,但尽量少重复
{n,m}? 重复n到m次,但尽量少重复
{n,}? 重复n次以上,但尽量少重复
//环视
'jeffs'.replace(/(?<=jeff)(?=s)/i, '"')
//顺序环视和逆向环视,?= 匹配的目标位置后紧跟s,匹配的目标位置前紧邻jeff jeff目标s,结果输出:jeff"s [^]: ^表示非 //示例:[^u] //[]里面的元字符只是普通字符 /03[-./]22/.test('03-22') 结果输出:true //() :标记一个子表达式的开始和结束位置。子表达式能够获取供之后使用 复制代码
由于匹配结果是按照()的个数和顺序决定的,重点是前面9个bash
最后两个[index: 0,input: 'http://test.com:8080?name=1&password=2#page1']是regexp.exec函数自带返回的服务器
因此上面的表达式能够拆分为以下子表达式:ide
(([^:]+:)\/\/(([^:\/\?#]+)(:\d+)?))(\/[^?#]*)?(\?[^#]*)?(#.*)?
(([^:]+:)\/\/(([^:\/\?#]+)(:\d+)?))
([^:]+:)
(([^:\/\?#]+)(:\d+)?)
([^:\/\?#]+)
(:\d+)?
(\/[^?#]*)?
(\?[^#]*)?
(#.*)?
复制代码
具体分析见下图:函数
思考题:ui
正则表达式分割之千分符格式:
213435324.099.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
复制代码
今天就到这里,喜欢记得点赞~