最近在補充基礎知識,看到了一道面試題 地址傳送點這裏 :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, ',')
複製代碼
今天就到這裏,喜歡記得點贊~