HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Javascript querystring to object conversion

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
javascriptquerystringobjectconversion

Problem

The below code converts the window.location.search querystring into a JavaScript object. In particular, if a key occurs more than once the resulting value in the object will be an array. Please feel free to comment on both readability and speed of execution. Thanks!

window.location.search.split(/[?&]/g).reduce(function (prev, cur, idx, arr) {
    var segment = cur.split("="),
        key = segment[0],
        val = segment[1];
    if (prev[key]) {
        if (prev[key] instanceof Array) {
            prev[key].push(val);
        } else {
            prev[key] = [prev[key], val];
        }
    } else {
        prev[key] = val;
    }
    return prev;
}, { });

Solution

The line if (typeof prev[key] === typeof []) { is... weird. If you're checking for a type specifically, check for it: if (typeof prev[key] === 'object') { - the way you're doing it there causes a new array literal to be instantiated needlessly, as well as a superfluous typeof operation, both inefficient and outright unnecessary.

Making an array out of repeating keys is fallacious - if a key is exactly repeated in a query string, only the right-most instance of that query string value will be received by the server. Further, in cases where the query string contains validly structured arrays (test=1&test2[]=2&test2[]=4), your code ends up with a key like test[], which is a nasty to access: results['test2[]'] is the only way to get at it (no dot syntax allowed).

EDIT
To clarify my remarks about duplicating keys, I purhaps mistakenly restricted my comments to Apache(Linux or Windows)/PHP - certainly other languages and platforms are relevant to the discussion. In the PHP language (what I am most familiar with), the query string test=1&test=2 will result in:

var_export($_GET);
/* array (
  'test' => '2',
) */


... as you can see, only the right-most value is the only one passed into the script. The way PHP expects duplicate query string keys is by use of [] in the query: test[]=1&test[]=2

var_export($_GET);
/*array (
  'test' => 
      array (
        0 => '1',
        1 => '2',
  ),
)*/


This behavior is the same for POST data on PHP - you must use name="myField[]" if multiple fields will use the same name, otherwise, only the last item in the form with a given name will be populated in PHP's $_POST data.

I am not set up to confirm the behavior of this in ASP (or other languages), however research has indicated that my assertion is still somewhat valid: https://stackoverflow.com/questions/6395290/how-may-i-add-integer-list-to-route/6396793#6396793. Please confirm if you are able: from what I have gathered the values would be passed to script as a comma-delimited list, but the language itself still rejects working with duplicate keys and a workaround is required.

If you can add some data about handling of duplicate keys in other server languages, please feel free to edit them into this answer. That said, I feel my criticism of this script's handling of duplicate keys stands, as well as the issue with "properly formed" (PHP) arrays in the query string - result['test[]'] is nasty.

Code Snippets

var_export($_GET);
/* array (
  'test' => '2',
) */
var_export($_GET);
/*array (
  'test' => 
      array (
        0 => '1',
        1 => '2',
  ),
)*/

Context

StackExchange Code Review Q#6062, answer score: 2

Revisions (0)

No revisions yet.