手写queryString.stringify

1,309 阅读1分钟

闲来无事,想写个大文件上传插件,其中涉及到发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=