以下是一个 JavaScript 实现,用于在查询字符串(query string)和对象之间进行相互转换,并自动处理 URL 编码和解码:
javascript
/**
* 将查询字符串解析为对象
* @param {string} queryString - 可选,默认为当前 URL 的查询部分
* @returns {Object} 解析后的对象
*/
function parseQuery(queryString = window.location.search) {
// 移除开头的 ? 字符
if (queryString.startsWith('?')) {
queryString = queryString.substring(1);
}
const result = {};
if (!queryString) return result;
// 分割参数对
const pairs = queryString.split('&');
for (const pair of pairs) {
const [encodedKey, encodedValue] = pair.split('=', 2);
// 处理没有值的参数(如 ?key 或 ?key=&value=1)
const key = encodedKey ? decodeURIComponent(encodedKey) : '';
const value = encodedValue !== undefined ? decodeURIComponent(encodedValue) : '';
// 处理重复键(转为数组)
if (result[key] !== undefined) {
if (!Array.isArray(result[key])) {
result[key] = [result[key]];
}
result[key].push(value);
} else {
result[key] = value;
}
}
return result;
}
/**
* 将对象转换为查询字符串
* @param {Object} obj - 需要转换的对象
* @returns {string} 转换后的查询字符串(不含 ? 前缀)
*/
function stringifyQuery(obj) {
if (!obj || typeof obj !== 'object') return '';
const parts = [];
for (const [key, value] of Object.entries(obj)) {
// 跳过值为 undefined 或 null 的属性
if (value === undefined || value === null) continue;
// 处理数组值
const values = Array.isArray(value) ? value : [value];
for (const v of values) {
// 处理空字符串
const encodedKey = encodeURIComponent(key);
const encodedValue = v !== '' ? encodeURIComponent(v) : '';
parts.push(`${encodedKey}=${encodedValue}`);
}
}
return parts.join('&');
}
// 示例用法
const queryObj = {
name: 'John Doe',
age: 30,
hobbies: ['coding', 'reading'],
specialChar: '@#$',
empty: '',
};
// 对象转查询字符串
const queryString = stringifyQuery(queryObj);
console.log(queryString);
// 输出: "name=John%20Doe&age=30&hobbies=coding&hobbies=reading&specialChar=%40%23%24&empty="
// 查询字符串转对象
const parsedObj = parseQuery('?name=John%20Doe&age=30&hobbies=coding&hobbies=reading&specialChar=%40%23%24&empty=');
console.log(parsedObj);
// 输出:
// {
// name: "John Doe",
// age: "30",
// hobbies: ["coding", "reading"],
// specialChar: "@#$",
// empty: ""
// }
核心特性:
-
完整的编码处理:
- 使用
encodeURIComponent
和decodeURIComponent
处理特殊字符 - 正确处理空格(转换为
%20
而非+
) - 支持所有需要编码的 URI 组件字符
- 使用
-
数组参数处理:
- 自动识别重复参数名并转换为数组
- 保持参数顺序(在支持的浏览器中)
-
空值处理:
- 正确处理空字符串参数(
key=
) - 跳过
undefined
和null
值
- 正确处理空字符串参数(
-
兼容性:
- 不依赖任何外部库
- 支持现代浏览器和 Node.js 环境
-
边缘情况处理:
- 自动去除查询字符串开头的
?
- 处理没有值的参数(如
?key
) - 处理 URL 中可能出现的双重编码问题
- 自动去除查询字符串开头的
使用场景:
- 解析 URL 查询参数
- 构建 API 请求参数
- 处理表单提交数据
- 实现 URL 状态管理
注意事项:
- 该实现将所有参数值视为字符串,数字或布尔值会被保留为字符串格式
- 对于复杂对象结构(嵌套对象),建议先转换为 JSON 字符串再作为参数值
- 编码遵循 RFC 3986 标准,空格会被编码为
%20
而非+
- 如果需要支持
+
表示空格的旧格式,可以在解码时添加额外处理