萬萬沒想到,你是個套路滿滿的parseUrl

當你看到parseUrl的時候,首先映入眼簾的應該是曾幾什麼時候在面試的時候,或多或少都有被說起到的問題前端

咱們不用太關心面試方面的東西,放輕鬆,不要帶着心理壓力,即便它是套路滿滿,咱們也依然能輕鬆搞定面試

parseUrl主要的用途就是解析URL的查詢字符串數組

那麼,咱們也無論什麼hash寫在#號後面的東東了,只回歸到?號後面的查詢字符串這裏bash

一眼萬年

遙想當年,當你看到這樣的字符串'q=nba&src=home&fr=so',第一反應就是,小場面,用split一頓分割唄,先分割&,再分割=,小case的事函數

既然你們都會,我也就不賣關子了,開始擼一把啦測試

這個parseUrl很普通

寫出一個普普統統的parseUrl,特別的normal,對於咱們前端兒來講仍是小菜一碟的ui

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        // 解構數組所對應的值
        const [key, value] = pair.split('=');
        // 將鍵值對寫入obj
        obj[key] = value;
        return obj;
    }, {});
}

// 測試用例1
let s1 = 'q=nba&src=home&fr=so';
console.log(parseUrl(s1));  // {q:'nba',src:'home',fr:'so'}
複製代碼

But,誰曾想,在你一頓操猛如虎的時候,其實已經埋下了一個小小的隱患編碼

若是測試用例是'q=nba&src=home&fr=so&fe',就會出現小問題了,請看大屏幕spa

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        const [key, value] = pair.split('=');
        obj[key] = value;
        return obj;
    }, {});
}

// 測試用例2
let s2 = 'q=nba&src=home&fr=so&fe';
console.log(parseUrl(s2));  // {q:'nba',src:'home',fr:'so',fe:undefined}
複製代碼

因爲測試用例中的fe是沒有value值的,因此直接就是unfefined,看似也不影響什麼code

不過這種狀況能處理的話,咱們就不能視而不見,下面來修改一下,很是的簡單

沒有value也得管

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        const [key, value] = pair.split('=');
        ++++++
        // 沒有value值的狀況,就返回obj中已有的內容
        if (!value) {
            return obj;
        }
        ++++++
        obj[key] = value;
        return obj;
    }, {});
}

// 測試用例2
let s2 = 'q=nba&src=home&fr=so&fe';
console.log(parseUrl(s2));  // {q:'nba',src:'home',fr:'so'}
複製代碼

小小的隱患被咱們輕易搞定了,咱們再來看另一種狀況

URL的查詢字符串是能夠輸入這樣的字符的'q=nba&fe[pro]=news&fe[pid]=result'

按照上面的寫法,打印出來是這樣的{q:'nba','fe[pro]':'news','fe[pid]':'result'}

實際上,以咱們熟知的知識體系來說,明顯能看出來fe實際上是個對象類型,因此本不應是這樣的,起碼是這樣的{q:'nba',fe:{pro:'news', pid:'result'}}

那麼讓咱們來再研究研究吧

層層深刻對象中

原理也是並不複雜,其實就是若是遇到這種看似對象類型的字符出現,咱們就把它當成對象來處理,處理完第一層後,再處理第二層,以此類推下去

function parseUrl(str) {
    return str.split('&').reduce((obj, pair) => {
        const [key, value] = pair.split('=');
        if (!value) {
            return obj;
        }
        // obj[key] = value   廢棄廢棄廢棄
        
        // 深刻到obj的內部去搞
        deepObj(obj, key.split(/[\[\]]/g).filter(v => v), value);
        return obj;
    }, {});
}
// 深度設置對象
function deepObj(obj, keys, value) {
    // 下面咱們全部涉及註釋部分,都用fe[pro]來講明一下
    
    // fe[pro]被正則處理,匹配[和],以[或]分割出來的數組是這樣的['fe', 'pro', '']
    // 而後咱們只取非空值部分,就用filter過濾了一下,獲得['fe', 'pro']
    console.log(keys);  // ['fe', 'pro']
    
    let i = 0;
    for (; i < keys.length - 1; i++) {
        let key = keys[i];
        // key值爲fe
        if (!obj[key]) {    // obj中沒有fe
            obj[key] = {};  // { fe: {} }
        }
        // 深刻到obj的下一層
        obj = obj[key];     // 引用fe這個對象{}
    }
    // 至關於在fe對象里加屬性,fe:{pro: 'news'}
    obj[keys[i]] = value;
}



// 測試用例3
let s3 = 'q=nba&fe[pro]=news&fe[pid]=result';
console.log(parseUrl(s3)); // {q:'nba',fe:{pro:'news', pid:'result'}}
複製代碼

上面的代碼,經過註釋的方式進行了簡單分析,但願你們均可以理解

接下來,咱們繼續說一種與對象相似的,那就是寫成數組的形式,且聽風吟,來看這個用例'q=nba&box[0]=one&box[1]=two'

這樣的寫法對於解析來講,應該是返回以下格式{q:'nba',box:['one', 'two']}

那麼,事不宜遲,咱們再回到deepObj裏看看如何處理吧

數組就該有你的樣子

function parseUrl(str) {
    ...省略
}

function deepObj(obj, keys, value) {
    let i = 0;
    for (; i < keys.length - 1; i++) {
        let key = keys[i];
        if (!obj[key]) {
            ++++++
            // 若是是數組的話,keys應該是這樣的['box', '0']
            // 因此來判斷keys的i+1位置(就是索引爲1),是否是數字就行
            // 是數字的話就當作數組類型來處理便可了
            if (keys[i + 1].match(/^\d+$/)) {
                obj[key] = [];
            } else {
                obj[key] = {};
            }
            ++++++
        }
        obj = obj[key]
    }
    obj[keys[i]] = value;
}


// 測試用例4
let s4 = 'q=nba&box[0]=one&box[1]=two';
console.log(parseUrl(s4));  // {q:'nba',box:['one', 'two']}
複製代碼

解碼百分比編碼

最後一種狀況是這樣的,'q=you%2Bme&name=jay%20chou',咱們看到了%號,也就是說好比像空格,+號這樣的特殊字符都被編碼了

因此,別慌,既然被編碼了,咱們就能夠利用提供好的解碼方法搞定,它就是decodeURIComponent

代碼也是很是好修改的,在deepObj函數中,只要將obj[keys[i]] = value改成obj[keys[i]] = decodeURIComponent(value)便可了,大功告成

function parseUrl(str) {
    ...省略
}
function deepObj(obj, keys, value) {
    ...省略
    obj[keys[i]] = decodeURIComponent(value);
}

// 測試用例5
let s5 = 'q=you%2Bme&name=jay%20chou';
console.log(parseUrl(s5));  // {q:'you+me',name:'jay chou'}
複製代碼

各顯神通

經過上面的4種套路,其實已經能考到不少人了,沒想到一個小小的解析查詢字符串的操做,竟然隱藏着如此神通

這也不得不讓人唏噓,JS的世界老是那麼的博大精深,不過,咱們仍是不會停下腳步,繼續努力學下去的

感謝你們的觀看,886

相關文章
相關標籤/搜索