闲来无事,想写个大文件上传插件,其中涉及到发xhr请求时将参数转化为查询字符串,不想使用任何库,作为学习,就自己琢磨实现了下queryString.stringify,代码如下:
/**
* 规则:
* 1. 嵌套的key转化为[key]
* 2. 当值为function、undefined时忽略
* 3. 值为null时转为''
* 4. 返回以&拼接的字符串
* */
const toString = Object.prototype.toString;
function isIgnore(val) {
return typeof val === 'function'
|| val === undefined;
}
function encode(val) {
return encodeURIComponent(val);
}
function hasOwn(o, k) {
return o.hasOwnProperty(k);
}
function isObject(val) {
return toString.call(val) === '[object Object]';
}
function getKey(key) {
return key[0] + key.slice(1).map(i => `${encode('[')}${i}${encode(']')}`).join('');
}
function commonHandler(key, result, val) {
if (!isIgnore(val)) {
if (isObject(val)) {
objectHandler(key, result, val);
key.pop();
}
else if (Array.isArray(val)) {
arrayHandler(key, result, val);
key.pop();
}
else if (val === null) {
result.push(`${getKey(key)}=`);
key.pop();
}
else {
result.push(`${getKey(key)}=${encode(val)}`);
key.pop();
}
}
}
function objectHandler(key, result, obj) {
for (let k in obj) {
if (hasOwn(obj, k)) {
key.push(k);
commonHandler(key, result, obj[k]);
}
}
}
function arrayHandler(key, result, arr) {
arr.forEach((val, k) => {
key.push(k);
commonHandler(key, result, val);
})
}
function stringify(obj) {
const key = [];
const result = [];
if (!isObject(obj)) {
return '';
}
objectHandler(key, result, obj);
return result.join('&');
}
console.log(stringify({n: 1, s: 'b', a: [1,2,{a: 1, b: 2}], o: {a: 1, b: 2, c: {a: 1, b: 2}}, b: false, nl: null, un: undefined, f: function () {}}));
// n=1&s=b&a%5B0%5D=1&a%5B1%5D=2&a%5B2%5D%5Ba%5D=1&a%5B2%5D%5Bb%5D=2&o%5Ba%5D=1&o%5Bb%5D=2&o%5Bc%5D%5Ba%5D=1&o%5Bc%5D%5Bb%5D=2&b=false&nl=
// n=1&s=b&a[0]=1&a[1]=2&a[2][a]=1&a[2][b]=2&o[a]=1&o[b]=2&o[c][a]=1&o[c][b]=2&b=false&nl=