如何在 JavaScript 中解析 URL:URL API 与手动解析
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 的。