小红书面试:如何解析URl?

781 阅读2分钟

如果给你一串如下的url

const url = "http://www.domain.com/order?user=admin&id=123&city=南昌&enabled";

要你解析成

{
  protocol: 'http',
  hostName: 'www.domain.com',
  path: '/order',
  query: { user: 'admin', id: '123', city: '南昌', enabled: true }
}

你会怎么做呢?

本文就带大家去一起解析一下这段url

首先我们明白在url中,协议之后都是://

所以我们可以

const protocolArr = url.split("://"); // [http,www.domain.com/order?user=admin&id=123&city=南昌&enabled]
const protocol = protocolArr[0]; // http

获取到协议

接下来就是去拿取域名了

在protocolArr中的第二个就是www.domain.com/order?user=admin&id=123&city=南昌&enabled

里面包括了域名,并且我们只需要通过/分割,拿到第一个就可以拿到域名了

  const hostName = protocolArr[1].split("/")[0]; // www.domain.com

继续需要拿到路由地址

const pathArr = protocolArr[1].split("?"); // [www.domain.com/order,user=admin&id=123&city=南昌&enabled]
const path = pathArr[0].split(hostName)[1]; // /order
  •  split("?") 将 URL 分割为路径和查询参数。
  •  split(hostName) 提取出路径部分,hostNamewww.domain.com

接下来就是获取参数了

  1. 分割查询字符串

    const queryArr = pathArr[1].split("&"); 
    

    这行代码将查询字符串(pathArr[1])按照 & 符号分割成一个数组。对于字符串 user=admin&id=123&city=南昌&enabledqueryArr 将会是:

    ['user=admin', 'id=123', 'city=南昌', 'enabled']
    
  2. 创建查询对象

    const query = {};
    

    这里创建一个空对象 query,用来存放解析后的查询参数。

  3. 遍历查询数组

    queryArr.forEach((item) => {
    

    通过 forEach 方法遍历每个查询参数。

  4. 处理每个查询项

    if (!item.includes("=")) {
        query[item] = true;
        return;
    }
    const itemArr = item.split("=");
    const key = itemArr[0];
    const value = decodeURI(itemArr[1]);
    
    • 如果查询项不包含 =,则将其视为一个布尔值参数,设置为 true
    • 否则,将查询项按 = 分割,得到键和值,并使用 decodeURI 对值进行解码。
  5. 处理重复的查询参数

    if (query[key] !== undefined) {
        if (Array.isArray(query[key])) {
            query[key].push(value);
        } else {
            query[key] = [query[key], value];
        }
    } else {
        query[key] = value;
    }
    
    • 如果该键已经存在:

      • 如果其值是数组,则将新值添加到数组中。
      • 否则,将原值和新值放入一个数组中。
    • 如果该键不存在,则直接将值赋给键。

全部完整代码为

// 解析url
const url = "http://www.domain.com/order?user=admin&id=123&city=南昌&enabled";
console.log(parse(url));

function parse(url) {
    const protocolArr = url.split("://"); // [http,www.domain.com/order?user=admin&id=123&city=南昌&enabled]
    const protocol = protocolArr[0]; // http
  const hostName = protocolArr[1].split("/")[0]; // www.domain.com
  const pathArr = protocolArr[1].split("?"); // [www.domain.com/order,user=admin&id=123&city=南昌&enabled]
  const path = pathArr[0].split(hostName)[1]; // /order

  const queryArr = pathArr[1].split("&"); // ['user=admin', 'id=123', 'city=南昌', 'enabled']
  const query = {};
  queryArr.forEach((item) => {
    if (!item.includes("=")) {
      query[item] = true;
      return;
    }
    const itemArr = item.split("=");
    const key = itemArr[0];
    const value = decodeURI(itemArr[1]);
    // 判断当前值在query中是否存在
    if (query[key] !== undefined) {
      if (Array.isArray(query[key])) {
        query[key].push(value);
      } else {
        query[key] = [query[key], value];
      }
    } else {
      query[key] = value;
    }
  });
  return {
    protocol,
    hostName,
    path,
    query,
  };
}

可以看到结果为

image.png

当然我们也可以使用

const url = "http://www.domain.com/order?user=admin&id=123&city=南昌&enabled";
console.log(new URL(url));

可以看到打印结果为

image.png

这里里面同样是可以拿到我们想要的结果的,如果需要处理成特定的结果我们就需要进行二次的处理

总结

以上就是如何解析URl的全部内容了,希望对你能够有所帮助!