For the most part this looks good to me - your code is easily understood and well formatted. However, there is still room for improvement.
Don't bother creating mapped
, that logic could easily be integrated into the reduce function and avoids an extra loop over the array.
Don't assign to an object just to return it, instead of doing var obj = ... return obj
just do return pairs.reduce(...
Parsing URLs is complicated. It's really easy to forget to encode / decode something when working with them. In this case, your code correctly decodes the query values, but fails to decode the query key - if my query is ?q%26=search
, I would have to use document.location.query['q%26']
instead of the expected document.location.query['q&']
. Is this likely to happen? Maybe not, but it should be handled.
What I mean to say is - don't reinvent the wheel. There is a build in URLSearchParams
object which does the parsing for you.
What should happen if the URL is ?q=1&q=2
? Should only the first value be kept? Only the last? What about ?q[]=1&q[]=2
? Should this result in an array as PHP does or keep a single value? Ignoring these cases might be fine for your use case now, but if someone else uses your code, you should consider and document these edge cases.
Here's how I would implement this extension, ignoring the PHPism of converting keys using []
to arrays, and taking the last value if the same key is specified multiple times. I've defined it as a function for ease of testing, but it could just as well be dropped into your get()
function.
function getQueryObject(query) {
const result = {};
const params = new URLSearchParams(query);
for (const [key, value] of params) {
result[key] = value;
}
return result;
}
;[
'?q=1&q=2',
'?q%26=URLUtils.searchParams&topic=api',
'?q[]=a',
'?q=with some spaces'
].forEach(query => {
console.log(query, '-->', getQueryObject(query))
})