最详细的解题,借鉴了题解区中的大神(忘记名字了),将每一步都仔细做了备注。
function geturl(sUrl, sKey) {
    let arr = sUrl.split("?")[1].split("#")[0]; //key=1&key=2&key=3&key=4&test=4
    if (sKey) { //有参数
        let strs = arr.split("&"); //'key=1', 'key=2', 'key=3', 'key=4', 'test=4'
        let arrs = new Array(); //创建一个新数组
        strs.forEach(item => {
            let tmp = item.split("="); //[ 'key', '1' ][ 'key', '2' ][ 'key', '3' ][ 'key', '4' ][ 'test', '4' ]
            if (tmp[0] === sKey) { //如果当前键的值===输入的键
                arrs.push(tmp[1]); //则将该键的值 放入数组中
            }
        })
        if (arrs.length == 1) { //如果只有输入的键查找结果只有一个
            return arrs[0]; //只返回当前键的值
        } else if (arrs.length == 0) { //如果找不到改键
            return ""; //返回空字符串
        } else {
            return arrs; //除开以上的结果,返回所有的键
        }
    } else { //没有指定参数,返回全部参数对象 或者{}
        if (arr == undefined || arr == "") {
            return {};
        } else {
            let strs = arr.split("&");
            let obj = new Object(); //创建一个新对象
            strs.forEach(item => {
                let tmp = item.split("=");
                if (!(tmp[0] in obj)) { //如果对象中没有该索引,就往对象中添加改索引
                    obj[tmp[0]] = []; //将新添加的属性tmp[0]的属性值设置为[] (为了下面使用push做铺垫)
                }
                obj[tmp[0]].push(tmp[1]); //依次将值放入对应的键名  (注意:只有数组才能用push函数)
            })
            return obj;
        }
    }
}