4

I know there are various libraries or methods to get the data from a queryString. However, I'm trying to learn javascript a bit so decided to write my own, as follows:

function parseQueryString() {
    var qs = window.location.href.split('?')[1];
    var item = qs.split('&');
    var data = {};
    for (var i=0; i < item.length; i++) {
        key = item[i].split('=')[0];
        value = item[i].split('=')[1];
        data[key] = value;
    }
    return data;
}

Does the above look like it's missing anything, or have any shortcomings? If so, how can I improve it?

5 Answers5

6

You can use the new "URLSearchParams" - but note that browser support is not universal (https://caniuse.com/#search=URLSearchParams)

var urlParams = new URLSearchParams(window.location.search);
var activeCategory, activeComponent;

  // sets the active navigation if there are query paramenters in the url
  if(urlParams.has('category')) {
    activeCategory = urlParams.get('category');
    activeComponent= urlParams.get('component');
  } else {
    activeCategory = null;
    activeComponent= null;
  }

  //eg: www.myShop.com.au?category=music&component=guitar
  // gives activeCategory="music"  and activeComponent = "guitar"

   //eg: www.myShop.com.au
  // gives activeCategory = null  and activeCcomponent = null
gavgrif
  • 13,077
  • 2
  • 17
  • 22
5

A few suggestions - consider using window.location.search to access the query string directly.

Also, you might want to factor in scenarios where "arrays" exist in your query string (ie multiple values sharing the same key). One way to handle that might be to return an array of values found for a key, in the data object that you return.

For more detail, see the comments in this updated version of the function:

function parseQueryString() {

    // Use location.search to access query string instead
    const qs = window.location.search.replace('?', '');

    const items = qs.split('&');

    // Consider using reduce to create the data mapping
    return items.reduce((data, item) => {

      const [rawKey, rawValue] = item.split('=');
      const key = decodeURIComponent(rawKey);
      const value = decodeURIComponent(rawValue);

      // Sometimes a query string can have multiple values 
      // for the same key, so to factor that case in, you
      // could collect an array of values for the same key
      if(data[key] !== undefined) {
        
        // If the value for this key was not previously an
        // array, update it
        if(!Array.isArray(data[key])) {
          data[key] = [ data[key] ]
        }       
        
        data[key].push(value)
      }
      else {
        
        data[key] = value
      }

      return data

    }, {})
}
Kędrzu
  • 2,265
  • 11
  • 21
Dacre Denny
  • 26,362
  • 5
  • 28
  • 48
1

You should always check length after split, before accessing an index, otherwise it'll cause an exception if url have no query string

 var qsarr = window.location.href.split('?');
  if(qsarr.length > 1)
  var qs=qsarr[1];

Same check while retrieving value from item inside loop

crack_iT
  • 1,321
  • 2
  • 12
  • 15
0

here is a variant of amiuhle's solution, with improved regex, using functional javascript (map, filter) to process the result. repeated keys like k=1&k=2&k=3 are parsed as array [1, 2, 3]. k=1=2=3 is parsed as value 1=2=3

// _get(key), similar to PHP $_GET[key]
// return array of values if key is repeated in query string
window._get = function(key) {
  let __get_obj;
  __get_obj = window.__get_obj || (function() {
    // parse query string
    const input = document.location.search;
    let __get_obj = {};
    const re = /([^?&=]+)(?:=([^&]+))?/g;
    let match;
    while (match = re.exec(input)) {
      // empty value = true
      const [k, v] = [
        decodeURIComponent(match[1]),
        // empty value = true
        (decodeURIComponent(match[2]) || true)
      ];
      if (k in __get_obj) {
        if (Array.isArray(__get_obj[k])) {
          __get_obj[k].push(v);
        } else {
          __get_obj[k] = [__get_obj[k], v];
      }} else {
        __get_obj[k] = v;
      }
    }
    return window.__get_obj = __get_obj;
  })();

  if (!key) return __get_obj;
  return __get_obj[key];
};

document.write(`input = ${document.location.search}<br/><br/>output:<br/>`)

// print all key-value pairs
Object.keys(_get()).forEach(key => (
  document.write(`${key} = ${_get(key)}<br/>`)
));
Mila Nautikus
  • 684
  • 6
  • 12
0

You can try URLSearchParams

// Search

const urlParams = new URLSearchParams(window.location.search);
const myParam = urlParams.get('myParam');

// Append

const urlParams = new URLSearchParams('?foo=bar&active=false');
const myParam = urlParams.get('foo');
console.log('foo is' , myParam)

urlParams.set('foo', 'baz')
console.log(urlParams.toString());
Shakil Alam
  • 99
  • 1
  • 6