万万没想到,你是个套路满满的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

相关文章
相关标签/搜索