从url中获取params参数并使用对象形式存储

2023/7/19 string

今天做了字节的一个笔试题,要求从url中取出parmas参数,将他们以键值对的形式存到对象中

还有一些额外的需求,具体的记不清了,只记得下面这些👇

  • 当传递重复的key时,不额外往对象中加入新的键值对,而是把这个key对应的val转换为数组的形式来存储他的多个val
  • vals 是基本数据类型时,要以对应的基本数据类型来存储

# 思路分析

既然是处理一个url中的params参数,那我们首先就要拿到params参数

1️⃣ 可以用正则(但是不容易记),正则是最方便的,但是正则记起来也是真难啊😢

1

配合replace使用就可以拿到params参数,进一步往对象中存储了

let regx = /([^&?=]+)=([^&?=]+)/g;
url.replace(regx, (...args) => {});

2️⃣ 可以发现,正则也是找的?,因为?后面就是params的内容,所以我们可以通过将?作为一个分割线,把url分成两部分,后面一部分就是我们要的结果

既然要分割,那就使用split() 👇

let params = str.split("?")[1];
let param = params.split("&");

/* 
params:  name=itclanCoder&study=css&study=js&study
=react&key=1
param:  [ 'name=itclanCoder', 'study=css', 'study=
js', 'study=react', 'key=1' ]
*/

拿到params参数之后,下一步就是往对象中存储它们了,这一步其实就不难了😄

let baseUrlStr =
  "https://coder.itclan.cn?name=itclanCoder&study=css&study=js&study=react&key=1";
// 参数转成对象
function queryString(str) {
  let params = str.split("?")[1]; //截取?号后的字符串即name=itclanCoder&study=css
  let param = params.split("&"); // 通过&符号进行分割即["name=itclanCoder", "study=css"]
  let obj = {}; // 用一个对象存储目标值
  for (let i = 0; i < param.length; i++) {
    // 循环遍历截取出来的param数组
    let paramsA = param[i].split("="); // 通过split,=继续对数组params每一项进行分割,生成数组["name", "itclanCoder"]
    let key = paramsA[0]; // 取数组项["name", "itclanCoder"]中第0位,即name
    let value = paramsA[1]; // 取数组项["name", "itclanCoder"]中第1位,即itclanCoder
    obj[key] = value;
  }
  return obj;
}
console.log("obj: ", queryString(baseUrlStr));

2

这时我们就可以写出来一个满足基本要求的方法了

# 💪 额外需求

1️⃣ 相同key的处理,可以看到上面的例子中,study是重复赋值的,但是我们一直在覆盖,所以obj最后只有最后一次的数据

既然要用数组来处理重复数据,那其实就是在往obj中放对象的时候加了一个判断,obj是否已经该key,如果有,再判断是否已经是数组了,如果是数组,就只需要push当前val即可,如果不是,就要把obj里的该key对应的val转换成数组形式,然后再push即可

let baseUrlStr =
  "https://coder.itclan.cn?name=itclanCoder&study=css&study=js&study=react&key=1";
// 参数转成对象
function queryString(str) {
  // 分割拿到params参数
  let params = str.split("?")[1];
  console.log("params: ", params);
  let param = params.split("&");
  console.log("param: ", param);
  let obj = {};
  for (let i = 0; i < param.length; i++) {
    let paramsA = param[i].split("=");
    let key = paramsA[0];
    let value = paramsA[1];

    if (obj[key]) {
      // 主要是在这里做了一下处理,判断值是不是一个数组
      // 是数组就保留数组,push新的值就可以
      // 不是数组就把obj[key]转换为数组的形式 —— [obj[obj[key]]], 再push
      obj[key] = Array.isArray(obj[key]) ? obj[key] : [obj[key]];
      obj[key].push(value);
    } else {
      obj[key] = value;
    }
  }
  return obj;
}
console.log("obj: ", queryString(baseUrlStr));

3

可以看到,此时study属性就以数组形式存储了

2️⃣ 基本数据类型

这里我的想法就比较简单了,对于Number,我选择用正则来处理,我的正则比较菜,只会处理正整数(包括0)的情况,不能处理浮点数

对于Boolean型的数据,因为只有两种情况,所以我是直接来对比判断的👇

let value = paramsA[1];
let reg = /^\d+$/g;
if (reg.test(value)) {
  value = parseInt(value);
}
if (value === "false" || value === "true") {
  value = Boolean(value);
}

加了上边这些代码之后,就可以拿到 Number 和 Boolean 类型的数据了

4

对于undefinednull我也是直接判断的,如果大家有更好的方法可以在下面评论嗷~

# 最终版本

let baseUrlStr =
  "https://coder.itclan.cn?name=itclanCoder&study=css&study=js&study=react&key=1&test=true";
// 参数转成对象
function queryString(str) {
  // 分割拿到params参数
  let params = str.split("?")[1];
  console.log("params: ", params);
  let param = params.split("&");
  console.log("param: ", param);
  let obj = {};
  for (let i = 0; i < param.length; i++) {
    let paramsA = param[i].split("=");
    let key = paramsA[0];
    let value = paramsA[1];
    let reg = /^\d+$/g;
    if (reg.test(value)) {
      value = parseInt(value);
    }
    if (value === "false" || value === "true") {
      value = Boolean(value);
    }
    if (value === "undefined") {
      value = undefined;
    }
    if (value === "null") {
      value = null;
    }
    if (obj[key]) {
      // 主要是在这里做了一下处理,判断值是不是一个数组
      // 是数组就保留数组,push新的值就可以
      // 不是数组就把obj[key]转换为数组的形式 —— [obj[obj[key]]], 再push
      obj[key] = Array.isArray(obj[key]) ? obj[key] : [obj[key]];
      obj[key].push(value);
    } else {
      obj[key] = value;
    }
  }
  return obj;
}
console.log("obj: ", queryString(baseUrlStr));
How to love
Lil Wayne