URL参数解析
实现 getParams 函数,将 URL 查询字符串解析为对象
问题
实现一个 getParams 函数,将 URL 中的查询参数解析为对象。
getParams('https://example.com?name=张三&age=18&hobby=reading&hobby=coding')
// { name: '张三', age: '18', hobby: ['reading', 'coding'] }
解答
方法一:使用 URLSearchParams
function getParams(url) {
const result = {}
// 创建 URL 对象,获取查询字符串
const searchParams = new URL(url).searchParams
// 遍历所有参数
for (const [key, value] of searchParams) {
if (result.hasOwnProperty(key)) {
// 已存在的 key,转为数组
result[key] = [].concat(result[key], value)
} else {
result[key] = value
}
}
return result
}
方法二:手动解析
function getParams(url) {
const result = {}
// 获取 ? 后面的查询字符串
const queryString = url.split('?')[1]
if (!queryString) return result
// 按 & 分割,处理每个键值对
queryString.split('&').forEach(pair => {
// 按第一个 = 分割(值中可能包含 =)
const [key, ...rest] = pair.split('=')
// 解码 URI 组件
const value = decodeURIComponent(rest.join('=') || '')
const decodedKey = decodeURIComponent(key)
if (result.hasOwnProperty(decodedKey)) {
// 重复的 key 转为数组
result[decodedKey] = [].concat(result[decodedKey], value)
} else {
result[decodedKey] = value
}
})
return result
}
测试用例
// 基本解析
getParams('https://example.com?name=tom&age=18')
// { name: 'tom', age: '18' }
// 重复参数
getParams('https://example.com?tag=js&tag=css&tag=html')
// { tag: ['js', 'css', 'html'] }
// 中文编码
getParams('https://example.com?name=%E5%BC%A0%E4%B8%89')
// { name: '张三' }
// 空值处理
getParams('https://example.com?empty=&flag')
// { empty: '', flag: '' }
// 无参数
getParams('https://example.com')
// {}
关键点
- 使用
URLSearchParams是最简洁的方案,自动处理编码 - 手动解析需要用
decodeURIComponent解码中文和特殊字符 - 相同 key 出现多次时,应合并为数组
- 注意处理边界情况:无参数、空值、值中包含
= split('=')只按第一个=分割,避免值被截断
目录