Sunny-117 / js-challenges

✨✨✨ Challenge your JavaScript programming limits step by step

Home Page:https://juejin.cn/column/7244788137410560055

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

解析 URL Params 为对象

Sunny-117 opened this issue · comments

commented
解析 URL Params 为对象
const url =
  "https://www.baidu.com/s?wd=%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E9%A2%98%E6%8A%A5%E5%91%8A&rsv_spt=1&rsv_iqid=0xa3f5eb180001d272&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=ib&rsv_sug3=2&rsv_n=2";

function urlPars(url) {
  if (typeof url !== "string") return new Error("不是字符串");
  let index = url.indexOf("?");
  url = url.substring(index + 1);
  let arr = url.split("&");
  let obj = {};
  for (const item of arr) {
    let arr = item.split("=");
    obj[arr[0]] = arr[1];
  }
  return obj;
}
console.table(urlPars(url));
const url =
	"http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled"

const parseUrl = (url: string) => {
	const paramsStr = /.+\?(.+)$/.exec(url)![1]
	const paramsArr = paramsStr.split("&")
        const paramsObj: any = {}

	paramsArr.forEach((param) => {
		if (/=/.test(param)) { // param有value的情况
			const [key, value] = param.split("=") // destruct key & value
			const decodedValue: string = decodeURIComponent(value)
			const parsedValue: string | number = /^\d+$/.test(decodedValue)
				? parseFloat(decodedValue)
				: decodedValue
			if (paramsObj.hasOwnProperty(key)) {
				paramsObj[key] = ([] as (string | number)[]).concat(
					paramsObj[key],
					parsedValue
				)
			} else {
				paramsObj[key] = parsedValue
			}
		} else { // param没有value的情况
			paramsObj[param] = true
		}
	})
	return paramsObj
}

const result = parseUrl(url)
console.log(result)
// expected { user: 'anonymous', id: [ 123, 456 ], city: '北京', enabled: true }
  • 这道题用正则才是正解
const url = "https://translate.google.com.hk/?pli=1&sl=en&tl=zh-CN&text=elint&op=translate";
function transform(url){
    const obj = {};
    url.replace(/[\?\&]([^=]+)=([^&]+)/g,function(str, $1, $2){
        obj[$1] = $2;
    })
    return obj;
}
console.log(transform(url));
commented

本道题有几个考查的点,上面没有考虑全

  1. 可以利用window.location.search获取URL?及以后的部分
  2. 如果存在多个相同的解析key,val应该是个数组
  3. 对于存在中文字符,需要通过encodeURIComponent进行处理
// let search = window.location.search;
let search =
  "?ie=utf-8&f=8&f=9&rsv_bp=1&tn=44004473_16_oem_dg&wd=mdn%20%E6%80%8E%E4%B9%88%E5%AF%B9%E4%B8%AD%E6%96%87%E8%BF%9B%E8%A1%8Cencode&oq=window.location.search&rsv_pq=80a41f180011305d&rsv_t=c725ldO%2FogrEf83WjL5vA%2B7sQvsvDoA4r8QtXgPXRrlH3PWNenJKQPppP95KZy5IamKx0YmFtVEg&rqlang=cn&rsv_dl=tb&rsv_enter=1&rsv_sug3=31&rsv_sug1=3&rsv_sug7=100&rsv_sug2=0&rsv_btype=t&inputT=4675&rsv_sug4=4675";
search = search.slice(1);
let obj = {};
const arr = search.split("&");
arr.forEach((item) => {
  let [key, val] = item.split("=");
  (key = encodeURIComponent(key)), (val = encodeURIComponent(val));
  if (obj[key]) {
    obj[key] = [obj[key]];
    obj[key].push(val);
  } else {
    obj[key] = val;
  }
});
console.log(obj);
  • 上述是不是解码用错了函数(decodeURIComponent)
  • 后面是不是需要先判断obj[key]已经有值且是数组的情况
  1. 正则:
function getURLParams(url) {
    let params = {};
    url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(match, key, value) {
        key = decodeURIComponent(key);
        value = decodeURIComponent(value);
       if (obj[key]) {
          if(Array.isArray(params[key])) {
            params[key].push(value);
          } else {
            params[key] = [params[key], value];
          }
      } else {
        params[key] = value;
      }
    });
    return params;
}

let url = "http://example.com/?param1=abc&param2=def";
console.log(getURLParams(url));  // 输出: { param1: 'abc', param2: 'def' }

正则表达式[?&]+([^=&]+)=([^&]*)的意思是:

[?&]+: 匹配一个或多个问号或者和符号。
([^=&]+): 匹配一次或多次不是等于号和和符号的字符(即参数名)。
=: 匹配等于号。
([^&]*): 匹配零次或多次不是和符号的字符(即参数值)。

  1. 暴力法
let search =
  "?ie=utf-8&f=8&f=9&rsv_bp=1&tn=44004473_16_oem_dg&wd=mdn%20%E6%80%8E%E4%B9%88%E5%AF%B9%E4%B8%AD%E6%96%87%E8%BF%9B%E8%A1%8Cencode&oq=window.location.search&rsv_pq=80a41f180011305d&rsv_t=c725ldO%2FogrEf83WjL5vA%2B7sQvsvDoA4r8QtXgPXRrlH3PWNenJKQPppP95KZy5IamKx0YmFtVEg&rqlang=cn&rsv_dl=tb&rsv_enter=1&rsv_sug3=31&rsv_sug1=3&rsv_sug7=100&rsv_sug2=0&rsv_btype=t&inputT=";

search = search.slice(1);
let obj = {};
const arr = search.split("&");
arr.forEach((item) => {
  let [key, val] = item.split("=");
  key = decodeURIComponent(key);
  val = decodeURIComponent(val);
  
  if (obj[key]) {
    if(Array.isArray(obj[key])) {
      obj[key].push(val);
    } else {
      obj[key] = [obj[key], val];
    }
  } else {
    obj[key] = val;
  }
});
console.log(obj);
function format(url) {
    let res = {}
    url = url.slice(url.indexOf('?') + 1)
    url.split('&').map(item => {
        let [key, val] = item.split('=')
        val = decodeURIComponent(val)
        if (res[key]) {
            if (Array.isArray(res[key])) {
                res[key].push(val)
            } else {
                res[key] = [res[key], val]
            }
        } else {
            res[key] = val
        }
    })
    return res
}
function formatUrlSearchParams(url) {
    return Object.fromEntries(new URLSearchParams(new URL(url).search).entries())
}