如何在 JavaScript 中解析 URL:URL API 与手动解析

发布: (2026年5月2日 GMT+8 18:33)
4 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的具体内容(文本),我将为您翻译成简体中文。

Source:

使用 URL

const url = new URL('https://example.com:8080/path/page?q=hello+world&lang=en#section');

url.protocol; // "https:"
url.hostname; // "example.com"
url.port;     // "8080"
url.host;     // "example.com:8080"
url.pathname; // "/path/page"
url.search;   // "?q=hello+world&lang=en"
url.hash;     // "#section"
url.origin;   // "https://example.com:8080"
url.href;     // full URL string

解析器会自动处理边缘情况。host 会省略标准端口:

new URL('http://example.com:80/').host; // "example.com"

使用 URLSearchParams 处理查询参数

Never split on & and = manually—values can contain encoded & and = characters. Use URLSearchParams instead:

const url = new URL('https://example.com?q=hello+world&tags=js&tags=css');
const params = url.searchParams;

params.get('q');        // "hello world" (decodes `+` as space)
params.getAll('tags'); // ["js", "css"]
params.has('tags');    // true

// Iterate all params
for (const [key, value] of params) {
  console.log(key, value);
}
// q hello world
// tags js
// tags css

构建查询字符串

const params = new URLSearchParams({
  q: 'hello world',
  sort: 'date',
  page: '1'
});
params.toString(); // "q=hello+world&sort=date&page=1"

追加而不替换

params.append('tags', 'javascript');
params.append('tags', 'css');
params.toString(); // "q=hello+world&sort=date&page=1&tags=javascript&tags=css"

修改现有 URL

const url = new URL('https://example.com?page=1&sort=date');

url.searchParams.set('page', '2');   // update
url.searchParams.delete('sort');    // remove
url.searchParams.append('filter', 'active'); // add

url.href; // "https://example.com/?page=2&filter=active"

解析相对 URL

new URL('/about', 'https://example.com').href;
// "https://example.com/about"

new URL('../images/photo.jpg', 'https://example.com/blog/post/').href;
// "https://example.com/blog/images/photo.jpg"

new URL('?page=2', 'https://example.com/articles').href;
// "https://example.com/articles?page=2"

这是一种在爬取或构建爬虫时解析相对链接的正确方式。

自动百分号编码

const url = new URL('https://example.com/search');
url.searchParams.set('q', 'café & creme brûlée');
url.href;
// "https://example.com/search?q=caf%C3%A9+%26+creme+br%C3%BBl%C3%A9e"

手动编码/解码

// Encode a component value (e.g., query parameter value)
encodeURIComponent('hello world & more');
// "hello%20world%20%26%20more"

// Encode a full URL (preserves :, /, ?, =, &, #, @)
encodeURI('https://example.com/path?q=hello world');
// "https://example.com/path?q=hello%20world"

// Decode
decodeURIComponent('hello%20world');
// "hello world"

验证 URL

function isValidUrl(string) {
  try {
    new URL(string);
    return true;
  } catch {
    return false;
  }
}

isValidUrl('https://example.com'); // true
isValidUrl('not a url');           // false
isValidUrl('//example.com');       // true (protocol‑relative)

如果你需要强制特定协议:

function isHttpUrl(string) {
  try {
    const url = new URL(string);
    return url.protocol === 'http:' || url.protocol === 'https:';
  } catch {
    return false;
  }
}

主机名 vs. host

new URL('https://sub.example.co.uk/path').hostname;
// "sub.example.co.uk"

new URL('https://example.com:443/path').host;     // "example.com:443"
new URL('https://example.com:443/path').hostname; // "example.com"

hostname 去除端口;host 包含端口。

Node.js 兼容性

URL 类自 Node.js v10 起全局可用。对于旧版本:

const { URL, URLSearchParams } = require('url');

它在浏览器的 Web Workers 和 Service Workers 中也可用。

传统的 <a> 元素技巧(仅限浏览器)

在出现 URL API 之前,开发者会使用 DOM 中的 <a> 元素来解析 URL:

const a = document.createElement('a');
a.href = 'https://example.com/path';
a.hostname; // "example.com"

这种做法只能在浏览器中使用,在某些边缘情况上可能会在不同浏览器之间表现不一致,并且不支持 URLSearchParams。应优先使用现代的 URL API

Conclusion

URL API 与 URLSearchParams 结合使用,消除了与查询字符串处理和边缘情况 URL 解析相关的一整类错误。如果你仍然在手动使用 ?& 进行拆分,请切换到该 API——你会惊讶于过去是如何在没有它的情况下解析 URL 的。

0 浏览
Back to Blog

相关文章

阅读更多 »

自己制作框架,有什么建议吗?

《Making my own framework》的封面图片。有什么建议吗?https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fde...