这是一个更新的版本,来自@oriadam / @error的
URLSearchParams
答案,支持多级嵌套。
const urlString = (data) => {
if (data == null) { return ""; }
const urlParams = new URLSearchParams();
const rbracket = /\[\]$/;
const add = (name, valueOrFunction) => {
const value = typeof valueOrFunction === "function" ? valueOrFunction() : valueOrFunction;
urlParams.append(name, value == null ? "" : value);
};
const buildParams = (prefix, obj) => {
if (Array.isArray(obj)) {
obj.forEach((value, index) => {
if (rbracket.test(prefix)) {
add(prefix, value);
} else {
const i = typeof value === "object" && value != null ? index : "";
buildParams(`${prefix}[${i}]`, value);
}
});
} else if (typeof obj === "object" && obj != null) {
for (const [name, value] of Object.entries(obj)) {
buildParams(`${prefix}[${name}]`, value);
}
} else {
add(prefix, obj);
}
};
if (Array.isArray(data) || data instanceof NodeList) {
data.forEach(el => add(el.name, el.value));
} else {
for (const [name, value] of Object.entries(data)) {
buildParams(name, value);
}
}
return urlParams.toString();
};
这是基于
jQuery 3.5.1源代码的,因此对于相同的输入,它应该产生与
$.param
相同的输出。唯一的区别是空格将被编码为
+
而不是
%20
。
我已经提供了
Fiddle,其中使用了
jQuery测试用例,所有测试都通过了。
编辑:如果您需要支持不支持URLSearchParams
类的环境,则需要使用数组和encodeURIComponent
方法的组合,如其他答案所示:
const urlString = (data) => {
if (data == null) { return ""; }
const urlParams = [];
const rbracket = /\[\]$/;
const add = (name, valueOrFunction) => {
let value = typeof valueOrFunction === "function" ? valueOrFunction() : valueOrFunction;
if (value == null) { value = ""; }
urlParams.push(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`);
};
const buildParams = (prefix, obj) => {
if (Array.isArray(obj)) {
obj.forEach((value, index) => {
if (rbracket.test(prefix)) {
add(prefix, value);
} else {
const i = typeof value === "object" && value != null ? index : "";
buildParams(`${prefix}[${i}]`, value);
}
});
} else if (typeof obj === "object" && obj != null) {
for (const [name, value] of Object.entries(obj)) {
buildParams(`${prefix}[${name}]`, value);
}
} else {
add(prefix, obj);
}
};
if (Array.isArray(data)) {
data.forEach(el => add(el.name, el.value));
} else {
for (const [name, value] of Object.entries(data)) {
buildParams(name, value);
}
}
return urlParams.join("&");
};
更新的测试Fiddle