In the process of our work, we often encounter the problem of transferring parameters from the URL. When the parameters are passed in the URL, we need to parse these parameters from the URL.

For example: www.toutiao.com/search/?key…

At this point we need to retrieve the keyword and its corresponding value from the URL and apply it to our other corresponding code logic.

General practice: We are only dealing with? The following parameters are processed, namely keyword=fabu&name=bgcolor

function parse (str) {
    if (typeofstr ! = ='string') return;
    return str.split('&').reduce((acc, cur) = > {
        var [key, value] = cur.split('=');
        // If no value exists, no value is required
        if(! value)return acc;
        acc[key] = value;
        returnacc; }}, {})/ / url
var url = 'keyword=fabu&name=bgcolor';
parse(url); {keyword: 'fabu', name: 'bgcolor'}
Copy the code

So here we are, we can basically parse the urls that we see all the time.

However, in the actual development process, we may encounter not such URLS, usually relatively complex urls, such as:

var str1 = 'a=1&b[name]=bgcolor&c[0]=c1&c[1]=c2&color=Deep%20color'
Copy the code

What do we get if we manipulate the URL the way we wrote it before?

parse(str1); 
Copy the code

The resulting value:

{
    "a": "1"."b['name']": "bgcolor"."c[0]": "c1"."c[1]": "c2"."color": "Deep%20color"
}
Copy the code

And that’s not what we want, that’s what we want

{
    "a": "1"."b": {
        "name": "bgcolor"
    },
    "c": [
        "c1"."c2"]."color": "Deep color"
}
Copy the code

So we need to modify our previous parse function

function parse (str) {
    if (typeofstr ! = ='string') return;
    return str.split('&').reduce((acc, cur) = > {
        var [key, value] = cur.split('=');
        // If no value exists, no value is required
        if(! value)return acc;
        // acc[key] = value; // No direct assignment can be performed here
        // We need to perform some operations on the key and value to make it return as expected
        deep_set(acc, key, value);
        returnacc; }}, {})// the deep_set function handles complex keys
function deep_set (o, path, value) {
    C [0] ==> b.name; c[0] ==> b.name; c.0; Then we start looping through the current converted path */
    var formatPath = path.replace(/[\[\]]/g.'. ').split('. ').filter(x= > x);
    var lens = formatPath.length;
      /* * The last item of the formatPath must be a primitive datatype, so we don't need to deal with this item * and we need to assign different datatype according to its attributes * for example, b[name] ==> [b, name] I +1 is a string, So is an object, we assign {} * c[0] ==> [c, 0] I +1 matches the number, so should be an array, we assign [] */
      for (var i = 0; i < lens - 1; i++) {
        if(! o[formatPath[i]]) { o[formatPath[i]] = formatPath[i+1].match(/^\d+$/g)? [] : {} } o = o[formatPath[i]]; } o[formatPath[i]] =decodeURIComponent(value);
}

// reparse the URL
var str = 'a=1&b[name]=bgcolor&c[0]=c1&c[1]=c2&color=Deep%20color';
parse(str);
Copy the code

Results obtained:

{
  a: '1'.b: { name: 'bgcolor' },
  c: [ 'c1'.'c2'].color: 'Deep color'
}
Copy the code

If deep_set does not have a formatPath[I], we assign it an empty array or an empty object according to the formatPath[I] type.

O is then reassigned to o[formatPath[I]] until all formatPath items have been traversed, and the last item is assigned value.

Write a blog for the first time, the expression is a little disorderly, do not know how to express better, please do not spray each big guy, if have a question can leave a message in the comment.