URL querystring parameter setting

Benchmark created by Jens Roland on


Description

Various algorithms, some based on the fast implementation for getting URL parameters by Andy E:

http://stackoverflow.com/questions/901115/get-querystring-values-with-jquery/2880929#2880929

(and a really good argument against using the jQuery.query plugin if you want speed and don't need array parameters)

Preparation HTML

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//test.blairmitchelmore.com/jquery.query/jquery.query.js"></script>

 
<script>
  // Test querystring object -- use http://stackoverflow.com/questions/901115/get-querystring-values-with-jquery/2880929#2880929 to populate this FAST
  var urlParams = {
   a: 'foo',
   b: 'bar wee',
   c: 'baz ',
   d: 'quux',
   e: 'xyzzy'
  };
  
  // Replacement for document.location.search since we are using a test page with no querystring
  var docLocSearch = '?a=foo&b=bar wee&c=baz&d=quux&e=xyzzy';
  
  // Test parameters to add to querystring
  var stuff = {
   a: 'more magic',
   b: 'even more magic',
   x: 'and even more magic',
  };
  
  
  // --------------------------------------------------------------------------
  
  function querySet1(key, value) {
   // Update a shallow clone of urlParams array (works whether key exists in array or not)
   var newParams = jQuery.extend({}, urlParams);
   newParams[key] = value;
  
   // Build new querystring from urlParams array
   var querystring = '';
   for (var param in newParams) {
    querystring += '&' + param + '=' + newParams[param];
   }
   // Remove leading '&' character
   querystring = querystring.substring(1);
  
   return querystring;
  }
  // --------------------------------------------------------------------------
  
  function querySet2(key, value) {
   var newParams = [];
   for (var param in urlParams) {
    if (param == key) newParams.push([param, value].join('='));
    else newParams.push([param, urlParams[param]].join('='));
   }
   var querystring = newParams.join('&');
  
   return querystring;
  }
  // --------------------------------------------------------------------------
  
  function querySet3(key, value) {
   var newParams = [];
   for (var param in urlParams) {
    if (param == key) newParams.push(param + '=' + value);
    else newParams.push(param + '=' + urlParams[param]);
   }
   var querystring = newParams.join('&');
  
   return querystring;
  }
  // --------------------------------------------------------------------------
  
  function querySet4(key, value) {
   var newParams = [key + '=' + value];
   for (var param in urlParams) {
    if (param != key) newParams.push(param + '=' + urlParams[param]);
   }
   var querystring = newParams.join('&');
  
   return querystring;
  }
  // --------------------------------------------------------------------------
  
  function querySet5(key, value) {
   var clonedParams = jQuery.extend({}, urlParams);
   clonedParams[key] = value;
  
   var pStrings = [];
   for (var param in clonedParams) {
    pStrings.push(param + '=' + clonedParams[param]);
   }
   var querystring = pStrings.join('&');
  
   return querystring;
  }
  // --------------------------------------------------------------------------
  // From http://www.west-wind.com/weblog/posts/884279.aspx
  
  function setUrlEncodedKey(key, value, query) {
   query = query || window.location.search;
   var q = query + "&";
   var re = new RegExp("[?|&]" + key + "=.*?&");
   if (!re.test(q)) q += key + "=" + encodeURI(value);
   else q = q.replace(re, "&" + key + "=" + encodeURIComponent(value) + "&");
   q = q.trimStart("&").trimEnd("&");
   return q[0] == "?" ? q : q = "?" + q;
  }
  String.prototype.trimEnd = function(c) {
   if (c) return this.replace(new RegExp(c.escapeRegExp() + "*$"), '');
   return this.replace(/\s+$/, '');
  }
  String.prototype.trimStart = function(c) {
   if (c) return this.replace(new RegExp("^" + c.escapeRegExp() + "*"), '');
   return this.replace(/^\s+/, '');
  }
  String.prototype.escapeRegExp = function() {
   return this.replace(/[.*+?^${}()|[\]\/\\]/g, "\\$0");
  };
  // --------------------------------------------------------------------------
  // Original algorithm with no precalculated querystring object
  
  function querySetOrig(key, value) {
   key = escape(key).toLowerCase();
   value = escape(value);
  
   // NOTE: Uses the docLocSearch string for this test
   //var kvp = document.location.search.substr(1).split('&');
   var kvp = docLocSearch.substr(1).split('&');
  
   var i = kvp.length;
   var x;
   while (i--) {
    x = kvp[i].split('=');
  
    if (x[0].toLowerCase() == key) {
     x[1] = value;
     kvp[i] = x.join('=');
     break;
    }
   }
  
   if (i < 0) {
    kvp[kvp.length] = [key, value].join('=');
   }
  
   // Returns the updated querystring
   return kvp.join('&');
  }
  // --------------------------------------------------------------------------
  // Implementation based on querySet4
  
  function queryPush(key, value) {
   // Unescape parameters (uncomment for proper (but slow) decoding)
   //key = decodeURIComponent(key.replace(/\+/g, " "));
   //value = decodeURIComponent(value.replace(/\+/g, " "));
   // Build parameter array including new key-value pair
   var newParams = [key + '=' + value];
   for (var param in urlParams) {
    if (param != key) newParams.push(param + '=' + urlParams[param]);
   }
  
   // Return the updated querystring
   return newParams.join('&');
  }
  // --------------------------------------------------------------------------
  // Version optimized for maximum performance in both Chrome & IE8
  
  
  function queryPush2(key, value) {
   // Unescape parameters (uncomment for proper (but slow) decoding)
   //key = decodeURIComponent(key.replace(/\+/g, " "));
   //value = decodeURIComponent(value.replace(/\+/g, " "));
   // Build parameter array including new key-value pair
   var newParams = [];
   for (var param in urlParams) {
    if (param != key) newParams.push(param + '=' + urlParams[param]);
   }
  
   // Return the updated querystring
   return newParams.join('&') + '&' + key + '=' + value;
  }
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
querySet1
for (var x in stuff) {
 var y = stuff[x];
 querySet1(x, y, false);
}
ready
querySet2
for (var x in stuff) {
 var y = stuff[x];
 querySet2(x, y, false);
}
ready
querySet3
for (var x in stuff) {
 var y = stuff[x];
 querySet3(x, y, false);
}
ready
querySet4
for (var x in stuff) {
 var y = stuff[x];
 querySet4(x, y, false);
}
ready
querySet5
for (var x in stuff) {
 var y = stuff[x];
 querySet5(x, y, false);
}
ready
setUrlEncodedKey
for (var x in stuff) {
 var y = stuff[x];
 setUrlEncodedKey(x, y);
}
ready
$.query.set
for (var x in stuff) {
 var y = stuff[x];
 $.query.set(x, y);
}
ready
querySetOrig
for (var x in stuff) {
 var y = stuff[x];
 querySetOrig(x, y);
}
ready
queryPush
for (var x in stuff) {
 var y = stuff[x];
 queryPush(x, y);
}
ready
queryPush2
for (var x in stuff) {
 var y = stuff[x];
 queryPush2(x, y);
}
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Jens Roland on