0

While I was looking for a way to return url parameter values, I've come across this bit of code.

Reference: https://html-online.com/articles/get-url-parameters-javascript/

function getUrlParts(href) {
    var partsSet = {};
    var parts = href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(a,key,value) {
        partsSet[key] = value;
    });
    return partsSet;
}

I managed to use this code to achieve what I wanted to do however I don't understand it. I tried to punch that regex bit on various regex utility website but no luck. I don't understand " , function(a,key,value) " this part as well. Please explain how could this code return url parameter values.

Newbie_Android
  • 225
  • 2
  • 3
  • 12
  • Did you looked at this [`String.replace MDN`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace) ? – Code Maniac Oct 03 '19 at 16:16
  • Hi, yes var str = "hi android"; var rep = str.replace("hi", "hello") and hi changes into hello. I was trying to apply this concept into that bit of code above but I don't get it due to "function (a,key,value) – Newbie_Android Oct 03 '19 at 16:23
  • 1
    Read the description given in the above link, callback of `replaced` function accepts different arguments, i.e (complete match, gourp1, gourp2...)` – Code Maniac Oct 03 '19 at 16:24
  • There are better ways... see https://developer.mozilla.org/en-US/docs/Web/API/URL – benvc Oct 03 '19 at 16:27
  • Code Maniac // I am currently reading the link you gave me. Still very hard to understand. I will try reading it till i get it. – Newbie_Android Oct 03 '19 at 16:30
  • Here is a simple example of an alternative approach: https://stackoverflow.com/questions/979975/how-to-get-the-value-from-the-get-parameters – benvc Oct 03 '19 at 16:37
  • // benvc Appreciate your help however I want to understand this regex and this code. I am sure there are better ways. and I thank you for your help – Newbie_Android Oct 03 '19 at 16:41
  • 1
    Fair enough, the capture groups, indicated by `()` in the regex, are key to understanding what is going on with this code. `replace()` is passing the entire match as the first parameter of the replacement function and then each of the capture group matches to the following two parameters of the replacement function. Each key and value are then being set as a key / value pair in the `partsSet` object. – benvc Oct 03 '19 at 16:50
  • // benvc Thank you very much. it helped – Newbie_Android Oct 03 '19 at 16:59

1 Answers1

2

⚠️ The answer to your question follows, but please note that in 2019 you should probably not be using this code. See the end of my answer for a better solution. ⚠️

Regexper does a pretty good job of demonstrating what this regular expression will match:

Railroad diagram from Regexper.com

In English, you can read this as:

  1. One or more ? or & characters, followed by
  2. group #1: one or more characters that aren't = or &, followed by
  3. an =, followed by
  4. group #2: zero or more characters that aren't &

Group #1 captures the parameter names and group #2 captures their values.

As for the callback function (function(a,key,value) { ...) passed to replace, let's ask MDN:

You can specify a function as the second parameter. In this case, the function will be invoked after the match has been performed. The function's result (return value) will be used as the replacement string. … Note that the function will be invoked multiple times for each full match to be replaced if the regular expression in the first parameter is global.

The arguments to the function are as follows:

  • match – The matched substring.
  • p1, p2, ... – The nth string found by a parenthesized capture group, provided the first argument to replace() was a RegExp object.

(Source: MDN: String.prototype.replace – Specifying a function as a parameter)

(I've omitted the rest as it doesn't pertain to our question.)

What this tells us is that the function is called for every match, i.e. every parameter name-value pair in the string, and that the second argument (p1, or key in your code) holds the string captured by group #1 and the third argument (p2/value) holds the string captured by group #2.

The code you've found is really using replace for its side-effect: It's a really simple way to iterate all of the matches in a string.


A better way

As noted in the blog post you linked to, if you're targeting current browsers, instead of parsing the query string manually you should use URLSearchParams, which is intended for this exact purpose:

const query = '?foo=1&bar=2';

const searchParams = new URLSearchParams(query);

// Get a specific param
const foo = searchParams.get('foo');
console.log('got foo:', foo);

// Iterate over all params
searchParams.forEach((val, key) => console.log(key, 'is', val));

URLSearchParams works in all modern browsers, including MS Edge ≥ 17 (but not IE). The also exist polyfills for older browsers.

Jordan Running
  • 102,619
  • 17
  • 182
  • 182
  • Thank you so much for your kind and descriptive explanation. it helped me finally to understand it. I will make sure to re write the code using the better way you suggested. – Newbie_Android Oct 03 '19 at 17:01